]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/callable_traits/detail/is_invocable_impl.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / callable_traits / detail / is_invocable_impl.hpp
1 /*!
2 @file
3
4 @Copyright Barrett Adair 2015-2017
5 Distributed under the Boost Software License, Version 1.0.
6 (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
7
8 */
9
10 #ifndef BOOST_CLBL_TRTS_IS_INVOCABLE_IMPL_HPP
11 #define BOOST_CLBL_TRTS_IS_INVOCABLE_IMPL_HPP
12
13 #include <boost/callable_traits/detail/config.hpp>
14 #include <boost/callable_traits/detail/forward_declarations.hpp>
15 #include <boost/callable_traits/detail/utility.hpp>
16 #include <type_traits>
17 #include <utility>
18
19 namespace boost { namespace callable_traits { namespace detail {
20
21 template<typename T>
22 struct can_dereference_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,
42 can_dereference_t<T>::value>;
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>
58 struct generalize_t<T, is_reference_wrapper<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>
66 using generalize = typename generalize_t<T>::type;
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()(Rgs&&... rgs) const ->
84 success<decltype(std::declval<U>()(static_cast<Rgs&&>(rgs)...))>;
85
86 auto operator()(...) 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,
100 typename Obj = generalize_if_dissimilar<class_t, U&&>>
101 auto operator()(U&& u, Rgs&&... rgs) const ->
102 success<decltype((std::declval<Obj>().*std::declval<Pmf>())(static_cast<Rgs&&>(rgs)...))>;
103
104 auto operator()(...) 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,
113 typename Obj = generalize_if_dissimilar<class_t, U&&>>
114 auto operator()(U&& u) const ->
115 success<decltype(std::declval<Obj>().*std::declval<Pmd>())>;
116
117 auto operator()(...) const -> substitution_failure;
118 };
119
120 template<typename T, typename... Args>
121 struct is_invocable_impl {
122 using traits = detail::traits<T>;
123 using test = detail::test_invoke<traits>;
124 using result = decltype(test{}(::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>
134 struct is_invocable_r_impl {
135 using traits = detail::traits<T>;
136 using test = detail::test_invoke<traits>;
137 using result = decltype(test{}(::std::declval<Args>()...));
138 using type = typename std::is_convertible<typename result::_::type, Ret>::type;
139 };
140
141 template<typename Ret, typename T, typename... Args>
142 struct is_invocable_r_impl<std::false_type, Ret, T, Args...> {
143 using type = std::false_type;
144 };
145
146 }}} // namespace boost::callable_traits::detail
147
148 #endif // #ifndef BOOST_CLBL_TRTS_IS_INVOCABLE_IMPL_HPP