1 /*============================================================================= 2 Copyright (c) 2015 Paul Fultz II 3 can_be_called.h 4 Distributed under the Boost Software License, Version 1.0. (See accompanying 5 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 ==============================================================================*/ 7 8 #ifndef BOOST_HOF_GUARD_CAN_BE_CALLED_H 9 #define BOOST_HOF_GUARD_CAN_BE_CALLED_H 10 11 #include <boost/hof/config.hpp> 12 #include <boost/hof/detail/and.hpp> 13 #include <boost/hof/detail/holder.hpp> 14 #include <boost/hof/detail/using.hpp> 15 16 namespace boost { namespace hof { namespace detail { 17 18 #if BOOST_HOF_NO_EXPRESSION_SFINAE 19 struct dont_care 20 { 21 dont_care(...); 22 }; 23 24 template<class T> 25 struct never_care 26 { 27 typedef dont_care type; 28 }; 29 30 struct cant_be_called_type 31 {}; 32 33 struct no_type 34 {}; 35 36 template<class F> 37 struct is_callable_wrapper_fallback 38 { 39 template<class... Ts> 40 auto operator()(Ts&&...) const 41 -> decltype(std::declval<F>()(std::declval<Ts>()...)); 42 }; 43 44 template<class T, class U=typename std::remove_cv<typename std::remove_reference<T>::type>::type> 45 struct is_callable_wrapper_base 46 : std::conditional<BOOST_HOF_IS_CLASS(U) && !BOOST_HOF_IS_FINAL(U), U, is_callable_wrapper_fallback<U>> 47 {}; 48 49 template<class F, class... Ts> 50 struct is_callable_wrapper : is_callable_wrapper_base<F>::type 51 { 52 is_callable_wrapper(); 53 typedef cant_be_called_type const &(*pointer_to_function)(typename never_care<Ts>::type...); 54 operator pointer_to_function() const; 55 }; 56 57 template<class T> 58 struct not_ 59 : std::integral_constant<bool, !T::value> 60 {}; 61 62 template<class F, class... Ts> 63 struct can_be_called 64 : not_<std::is_same<cant_be_called_type, typename std::decay<decltype( 65 is_callable_wrapper<F, Ts...>()(std::declval<Ts>()...) 66 )>::type>> 67 {}; 68 69 template<class F, class... Ts> 70 struct check_args; 71 72 template<class Res, class... Ts, class... Us> 73 struct check_args<Res(Us...), Ts...> 74 : and_<std::is_convertible<Ts, Us>...> 75 {}; 76 77 template<class Res, class... Ts, class... Us> 78 struct can_be_called<Res(*)(Us...), Ts...> 79 : std::conditional<sizeof...(Ts) == sizeof...(Us), 80 check_args<Res(Us...), Ts...>, 81 std::false_type 82 >::type 83 {}; 84 85 template<class Res, class... Ts, class... Us> 86 struct can_be_called<Res(Us...), Ts...> 87 : std::conditional<sizeof...(Ts) == sizeof...(Us), 88 check_args<Res(Us...), Ts...>, 89 std::false_type 90 >::type 91 {}; 92 93 #else 94 95 template<class T> 96 T&& called_val() noexcept; 97 98 template<class... Ts> 99 struct callable_args 100 {}; 101 102 template<class F, class Args, class=void> 103 struct can_be_called_impl 104 : std::false_type 105 {}; 106 107 template<class F, class... Args> 108 struct can_be_called_impl<F, callable_args<Args...>, typename detail::holder< 109 decltype( boost::hof::detail::called_val<F>()(boost::hof::detail::called_val<Args>()...) ) 110 >::type> 111 : std::true_type 112 {}; 113 114 template<class F, class... Ts> 115 BOOST_HOF_USING(can_be_called, can_be_called_impl<F, detail::callable_args<Ts...>>); 116 117 #endif 118 119 }}} // namespace boost::hof 120 121 #endif 122