File indexing completed on 2025-01-18 09:29:45
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_CLBL_TRTS_IS_INVOCABLE_IMPL_HPP
0011 #define BOOST_CLBL_TRTS_IS_INVOCABLE_IMPL_HPP
0012
0013 #include <boost/callable_traits/detail/config.hpp>
0014 #include <boost/callable_traits/detail/forward_declarations.hpp>
0015 #include <boost/callable_traits/detail/utility.hpp>
0016 #include <type_traits>
0017 #include <utility>
0018
0019 namespace boost { namespace callable_traits { namespace detail {
0020
0021 template<typename T>
0022 struct can_dereference_t
0023 {
0024 template<typename>
0025 struct check {};
0026
0027 template<typename U>
0028 static std::int8_t test(
0029 check<typename std::remove_reference<decltype(*std::declval<U>())>::type>*
0030 );
0031
0032 template<typename>
0033 static std::int16_t test(...);
0034
0035 static constexpr const bool value =
0036 sizeof(test<T>(nullptr)) == sizeof(std::int8_t);
0037 };
0038
0039
0040 template<typename T>
0041 using can_dereference = std::integral_constant<bool,
0042 can_dereference_t<T>::value>;
0043
0044
0045 template<typename T, typename = std::true_type>
0046 struct generalize_t {
0047 using type = T;
0048 };
0049
0050 template<typename T>
0051 struct generalize_t<T, std::integral_constant<bool,
0052 can_dereference<T>::value && !is_reference_wrapper<T>::value
0053 >>{
0054 using type = decltype(*std::declval<T>());
0055 };
0056
0057 template<typename T>
0058 struct generalize_t<T, is_reference_wrapper<T>> {
0059 using type = decltype(std::declval<T>().get());
0060 };
0061
0062
0063
0064
0065 template<typename T>
0066 using generalize = typename generalize_t<T>::type;
0067
0068
0069 template<typename Base, typename T,
0070 typename IsBaseOf = std::is_base_of<Base, shallow_decay<T>>,
0071 typename IsSame = std::is_same<Base, shallow_decay<T>>>
0072 using generalize_if_dissimilar = typename std::conditional<
0073 IsBaseOf::value || IsSame::value, T, generalize<T>>::type;
0074
0075 template<typename Traits, bool = Traits::is_const_member::value
0076 || Traits::is_volatile_member::value
0077 || Traits::is_lvalue_reference_member::value
0078 || Traits::is_rvalue_reference_member::value>
0079 struct test_invoke {
0080
0081 template<typename... Rgs,
0082 typename U = typename Traits::type>
0083 auto operator()(int, Rgs&&... rgs) const ->
0084 success<decltype(std::declval<U>()(static_cast<Rgs&&>(rgs)...))>;
0085
0086 auto operator()(long, ...) const -> substitution_failure;
0087 };
0088
0089 template<typename F>
0090 struct test_invoke<function<F>, true > {
0091 auto operator()(...) const -> substitution_failure;
0092 };
0093
0094 template<typename Pmf, bool Ignored>
0095 struct test_invoke<pmf<Pmf>, Ignored> {
0096
0097 using class_t = typename pmf<Pmf>::class_type;
0098
0099 template<typename U, typename... Rgs,
0100 typename Obj = generalize_if_dissimilar<class_t, U&&>>
0101 auto operator()(int, U&& u, Rgs&&... rgs) const ->
0102 success<decltype((std::declval<Obj>().*std::declval<Pmf>())(static_cast<Rgs&&>(rgs)...))>;
0103
0104 auto operator()(long, ...) const -> substitution_failure;
0105 };
0106
0107 template<typename Pmd, bool Ignored>
0108 struct test_invoke<pmd<Pmd>, Ignored> {
0109
0110 using class_t = typename pmd<Pmd>::class_type;
0111
0112 template<typename U,
0113 typename Obj = generalize_if_dissimilar<class_t, U&&>>
0114 auto operator()(int, U&& u) const ->
0115 success<decltype(std::declval<Obj>().*std::declval<Pmd>())>;
0116
0117 auto operator()(long, ...) const -> substitution_failure;
0118 };
0119
0120 template<typename T, typename... Args>
0121 struct is_invocable_impl {
0122 using traits = detail::traits<T>;
0123 using test = detail::test_invoke<traits>;
0124 using result = decltype(test{}(0, ::std::declval<Args>()...));
0125 using type = std::integral_constant<bool, result::value>;
0126 };
0127
0128 template<typename... Args>
0129 struct is_invocable_impl<void, Args...> {
0130 using type = std::false_type;
0131 };
0132
0133 template<typename IsInvocable, typename Ret, typename T, typename... Args>
0134 struct is_invocable_r_impl {
0135 using traits = detail::traits<T>;
0136 using test = detail::test_invoke<traits>;
0137 using result = decltype(test{}(0, ::std::declval<Args>()...));
0138 using type = std::integral_constant<bool,
0139 std::is_convertible<typename result::_::type, Ret>::value
0140 || std::is_same<Ret, void>::value>;
0141 };
0142
0143 template<typename Ret, typename T, typename... Args>
0144 struct is_invocable_r_impl<std::false_type, Ret, T, Args...> {
0145 using type = std::false_type;
0146 };
0147
0148 }}}
0149
0150 #endif