is_invocable_impl.hpp
Go to the documentation of this file.
1 
10 #ifndef BOOST_CLBL_TRTS_IS_INVOCABLE_IMPL_HPP
11 #define BOOST_CLBL_TRTS_IS_INVOCABLE_IMPL_HPP
12 
16 #include <type_traits>
17 #include <utility>
18 
19 namespace boost { namespace callable_traits { namespace detail {
20 
21  template<typename T>
23  {
24  template<typename>
25  struct check {};
26 
27  template<typename U>
28  static std::int8_t test(
29  check<typename std::remove_reference<decltype(*std::declval<U>())>::type>*
30  );
31 
32  template<typename>
33  static std::int16_t test(...);
34 
35  static constexpr const bool value =
36  sizeof(test<T>(nullptr)) == sizeof(std::int8_t);
37  };
38 
39  //returns std::true_type for pointers and smart pointers
40  template<typename T>
41  using can_dereference = std::integral_constant<bool,
43 
44 
45  template<typename T, typename = std::true_type>
46  struct generalize_t {
47  using type = T;
48  };
49 
50  template<typename T>
51  struct generalize_t<T, std::integral_constant<bool,
52  can_dereference<T>::value && !is_reference_wrapper<T>::value
53  >>{
54  using type = decltype(*std::declval<T>());
55  };
56 
57  template<typename T>
59  using type = decltype(std::declval<T>().get());
60  };
61 
62  // When T is a pointer, generalize<T> is the resulting type of the
63  // pointer dereferenced. When T is an std::reference_wrapper, generalize<T>
64  // is the underlying reference type. Otherwise, generalize<T> is T.
65  template<typename T>
67 
68  // handles the member pointer rules of INVOKE
69  template<typename Base, typename T,
70  typename IsBaseOf = std::is_base_of<Base, shallow_decay<T>>,
71  typename IsSame = std::is_same<Base, shallow_decay<T>>>
72  using generalize_if_dissimilar = typename std::conditional<
73  IsBaseOf::value || IsSame::value, T, generalize<T>>::type;
74 
75  template<typename Traits, bool = Traits::is_const_member::value
76  || Traits::is_volatile_member::value
77  || Traits::is_lvalue_reference_member::value
78  || Traits::is_rvalue_reference_member::value>
79  struct test_invoke {
80 
81  template<typename... Rgs,
82  typename U = typename Traits::type>
83  auto operator()(int, Rgs&&... rgs) const ->
84  success<decltype(std::declval<U>()(static_cast<Rgs&&>(rgs)...))>;
85 
86  auto operator()(long, ...) const -> substitution_failure;
87  };
88 
89  template<typename F>
90  struct test_invoke<function<F>, true /*abominable*/> {
91  auto operator()(...) const -> substitution_failure;
92  };
93 
94  template<typename Pmf, bool Ignored>
95  struct test_invoke<pmf<Pmf>, Ignored> {
96 
97  using class_t = typename pmf<Pmf>::class_type;
98 
99  template<typename U, typename... Rgs,
101  auto operator()(int, U&& u, Rgs&&... rgs) const ->
102  success<decltype((std::declval<Obj>().*std::declval<Pmf>())(static_cast<Rgs&&>(rgs)...))>;
103 
104  auto operator()(long, ...) const -> substitution_failure;
105  };
106 
107  template<typename Pmd, bool Ignored>
108  struct test_invoke<pmd<Pmd>, Ignored> {
109 
110  using class_t = typename pmd<Pmd>::class_type;
111 
112  template<typename U,
114  auto operator()(int, U&& u) const ->
115  success<decltype(std::declval<Obj>().*std::declval<Pmd>())>;
116 
117  auto operator()(long, ...) const -> substitution_failure;
118  };
119 
120  template<typename T, typename... Args>
124  using result = decltype(test{}(0, ::std::declval<Args>()...));
125  using type = std::integral_constant<bool, result::value>;
126  };
127 
128  template<typename... Args>
129  struct is_invocable_impl<void, Args...> {
130  using type = std::false_type;
131  };
132 
133  template<typename IsInvocable, typename Ret, typename T, typename... Args>
137  using result = decltype(test{}(0, ::std::declval<Args>()...));
138  using type = std::integral_constant<bool,
139  std::is_convertible<typename result::_::type, Ret>::value
140  || std::is_same<Ret, void>::value>;
141  };
142 
143  template<typename Ret, typename T, typename... Args>
144  struct is_invocable_r_impl<std::false_type, Ret, T, Args...> {
145  using type = std::false_type;
146  };
147 
148 }}} // namespace boost::callable_traits::detail
149 
150 #endif // #ifndef BOOST_CLBL_TRTS_IS_INVOCABLE_IMPL_HPP
constexpr auto get(span< E, S > s) -> decltype(s[N])
Definition: span.h:492
std::integral_constant< bool, can_dereference_t< T >::value > can_dereference
typename std::conditional< IsBaseOf::value||IsSame::value, T, generalize< T > >::type generalize_if_dissimilar
typename BOOST_CLBL_TRTS_DISJUNCTION(function_object< unwrap_reference< T > >, function< T >, pmf< T >, pmd< T >, default_callable_traits< T >)::traits traits
Definition: traits.hpp:25
typename is_reference_wrapper_t< shallow_decay< T > >::type is_reference_wrapper
Definition: utility.hpp:93
typename generalize_t< T >::type generalize
static std::int8_t test(check< typename std::remove_reference< decltype(*std::declval< U >())>::type > *)
decltype(test{}(0, ::std::declval< Args >()...)) result
std::integral_constant< bool, result::value > type
decltype(test{}(0, ::std::declval< Args >()...)) result
std::integral_constant< bool, std::is_convertible< typename result::_::type, Ret >::value||std::is_same< Ret, void >::value > type
auto operator()(long,...) const -> substitution_failure
auto operator()(int, U &&u) const -> success< decltype(std::declval< Obj >().*std::declval< Pmd >())>
auto operator()(long,...) const -> substitution_failure
auto operator()(int, U &&u, Rgs &&... rgs) const -> success< decltype((std::declval< Obj >().*std::declval< Pmf >())(static_cast< Rgs && >(rgs)...))>
auto operator()(int, Rgs &&... rgs) const -> success< decltype(std::declval< U >()(static_cast< Rgs && >(rgs)...))>
auto operator()(long,...) const -> substitution_failure