Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:38:14

0001 /*=============================================================================
0002     Copyright (c) 2015 Paul Fultz II
0003     can_be_called.h
0004     Distributed under the Boost Software License, Version 1.0. (See accompanying
0005     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 ==============================================================================*/
0007 
0008 #ifndef BOOST_HOF_GUARD_CAN_BE_CALLED_H
0009 #define BOOST_HOF_GUARD_CAN_BE_CALLED_H
0010 
0011 #include <boost/hof/config.hpp>
0012 #include <boost/hof/detail/and.hpp>
0013 #include <boost/hof/detail/holder.hpp>
0014 #include <boost/hof/detail/using.hpp>
0015 
0016 namespace boost { namespace hof { namespace detail {
0017 
0018 #if BOOST_HOF_NO_EXPRESSION_SFINAE
0019 struct dont_care
0020 {
0021     dont_care(...);
0022 };
0023 
0024 template<class T>
0025 struct never_care
0026 {
0027     typedef dont_care type;
0028 };
0029 
0030 struct cant_be_called_type
0031 {};
0032 
0033 struct no_type
0034 {};
0035 
0036 template<class F>
0037 struct is_callable_wrapper_fallback
0038 {
0039     template<class... Ts>
0040     auto operator()(Ts&&...) const 
0041     -> decltype(std::declval<F>()(std::declval<Ts>()...));
0042 };
0043 
0044 template<class T, class U=typename std::remove_cv<typename std::remove_reference<T>::type>::type>
0045 struct is_callable_wrapper_base
0046 : std::conditional<BOOST_HOF_IS_CLASS(U) && !BOOST_HOF_IS_FINAL(U), U, is_callable_wrapper_fallback<U>>
0047 {};
0048 
0049 template<class F, class... Ts>
0050 struct is_callable_wrapper : is_callable_wrapper_base<F>::type
0051 {
0052     is_callable_wrapper();
0053     typedef cant_be_called_type const &(*pointer_to_function)(typename never_care<Ts>::type...);
0054     operator pointer_to_function() const;
0055 };
0056 
0057 template<class T>
0058 struct not_
0059 : std::integral_constant<bool, !T::value>
0060 {};
0061 
0062 template<class F, class... Ts>
0063 struct can_be_called
0064 : not_<std::is_same<cant_be_called_type, typename std::decay<decltype(
0065     is_callable_wrapper<F, Ts...>()(std::declval<Ts>()...)
0066 )>::type>>
0067 {};
0068 
0069 template<class F, class... Ts>
0070 struct check_args;
0071 
0072 template<class Res, class... Ts, class... Us>
0073 struct check_args<Res(Us...), Ts...>
0074 : and_<std::is_convertible<Ts, Us>...>
0075 {};
0076 
0077 template<class Res, class... Ts, class... Us>
0078 struct can_be_called<Res(*)(Us...), Ts...>
0079 : std::conditional<sizeof...(Ts) == sizeof...(Us), 
0080     check_args<Res(Us...), Ts...>, 
0081     std::false_type
0082 >::type
0083 {};
0084 
0085 template<class Res, class... Ts, class... Us>
0086 struct can_be_called<Res(Us...), Ts...>
0087 : std::conditional<sizeof...(Ts) == sizeof...(Us), 
0088     check_args<Res(Us...), Ts...>, 
0089     std::false_type
0090 >::type
0091 {};
0092 
0093 #else
0094 
0095 template<class T>
0096 T&& called_val() noexcept;
0097 
0098 template<class... Ts>
0099 struct callable_args
0100 {};
0101 
0102 template<class F, class Args, class=void>
0103 struct can_be_called_impl
0104 : std::false_type
0105 {};
0106 
0107 template<class F, class... Args>
0108 struct can_be_called_impl<F, callable_args<Args...>, typename detail::holder<
0109     decltype( boost::hof::detail::called_val<F>()(boost::hof::detail::called_val<Args>()...) )
0110 >::type>
0111 : std::true_type
0112 {};
0113 
0114 template<class F, class... Ts>
0115 BOOST_HOF_USING(can_be_called, can_be_called_impl<F, detail::callable_args<Ts...>>);
0116 
0117 #endif
0118 
0119 }}} // namespace boost::hof
0120 
0121 #endif