File indexing completed on 2025-01-18 09:38:14
0001
0002
0003
0004
0005
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 }}}
0120
0121 #endif