]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/histogram/detail/detect.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / histogram / detail / detect.hpp
1 // Copyright 2015-2019 Hans Dembinski
2 //
3 // Distributed under the Boost Software License, Version 1.0.
4 // (See accompanying file LICENSE_1_0.txt
5 // or copy at http://www.boost.org/LICENSE_1_0.txt)
6
7 #ifndef BOOST_HISTOGRAM_DETAIL_DETECT_HPP
8 #define BOOST_HISTOGRAM_DETAIL_DETECT_HPP
9
10 #include <boost/histogram/fwd.hpp>
11 #include <boost/mp11/algorithm.hpp>
12 #include <boost/mp11/function.hpp>
13 #include <boost/mp11/utility.hpp>
14 #include <boost/variant2/variant.hpp>
15 #include <iterator>
16 #include <tuple>
17 #include <type_traits>
18
19 namespace boost {
20 namespace histogram {
21 namespace detail {
22
23 #define BOOST_HISTOGRAM_DETAIL_DETECT(name, cond) \
24 template <class T> \
25 using name##_impl = decltype(cond); \
26 template <class T> \
27 using name = typename boost::mp11::mp_valid<name##_impl, T>::type
28
29 #define BOOST_HISTOGRAM_DETAIL_DETECT_BINARY(name, cond) \
30 template <class T, class U> \
31 using name##_impl = decltype(cond); \
32 template <class T, class U = T> \
33 using name = typename boost::mp11::mp_valid<name##_impl, T, U>::type
34
35 // metadata has overloads, trying to get pmf in this case always fails
36 BOOST_HISTOGRAM_DETAIL_DETECT(has_method_metadata, (std::declval<T&>().metadata()));
37
38 // resize has overloads, trying to get pmf in this case always fails
39 BOOST_HISTOGRAM_DETAIL_DETECT(has_method_resize, (std::declval<T&>().resize(0)));
40
41 BOOST_HISTOGRAM_DETAIL_DETECT(has_method_size, &T::size);
42
43 BOOST_HISTOGRAM_DETAIL_DETECT(has_method_clear, &T::clear);
44
45 BOOST_HISTOGRAM_DETAIL_DETECT(has_method_lower, &T::lower);
46
47 BOOST_HISTOGRAM_DETAIL_DETECT(has_method_value, &T::value);
48
49 BOOST_HISTOGRAM_DETAIL_DETECT(has_method_update, &T::update);
50
51 // reset has overloads, trying to get pmf in this case always fails
52 BOOST_HISTOGRAM_DETAIL_DETECT(has_method_reset, (std::declval<T>().reset(0)));
53
54 BOOST_HISTOGRAM_DETAIL_DETECT(has_method_options, &T::options);
55
56 BOOST_HISTOGRAM_DETAIL_DETECT(has_allocator, &T::get_allocator);
57
58 BOOST_HISTOGRAM_DETAIL_DETECT(is_indexable, (std::declval<T&>()[0]));
59
60 BOOST_HISTOGRAM_DETAIL_DETECT_BINARY(
61 is_transform,
62 (std::declval<T&>().inverse(std::declval<T&>().forward(std::declval<U>()))));
63
64 BOOST_HISTOGRAM_DETAIL_DETECT(is_indexable_container, (std::declval<T>()[0], &T::size,
65 std::begin(std::declval<T>()),
66 std::end(std::declval<T>())));
67
68 BOOST_HISTOGRAM_DETAIL_DETECT(is_vector_like,
69 (std::declval<T>()[0], &T::size,
70 std::declval<T>().resize(0), std::begin(std::declval<T>()),
71 std::end(std::declval<T>())));
72
73 BOOST_HISTOGRAM_DETAIL_DETECT(is_array_like,
74 (std::declval<T>()[0], &T::size, std::tuple_size<T>::value,
75 std::begin(std::declval<T>()),
76 std::end(std::declval<T>())));
77
78 BOOST_HISTOGRAM_DETAIL_DETECT(is_map_like, (std::declval<typename T::key_type>(),
79 std::declval<typename T::mapped_type>(),
80 std::begin(std::declval<T>()),
81 std::end(std::declval<T>())));
82
83 // ok: is_axis is false for axis::variant, because T::index is templated
84 BOOST_HISTOGRAM_DETAIL_DETECT(is_axis, (&T::size, &T::index));
85
86 BOOST_HISTOGRAM_DETAIL_DETECT(is_iterable, (std::begin(std::declval<T&>()),
87 std::end(std::declval<T&>())));
88
89 BOOST_HISTOGRAM_DETAIL_DETECT(is_iterator,
90 (typename std::iterator_traits<T>::iterator_category()));
91
92 BOOST_HISTOGRAM_DETAIL_DETECT(is_streamable,
93 (std::declval<std::ostream&>() << std::declval<T&>()));
94
95 BOOST_HISTOGRAM_DETAIL_DETECT(has_operator_preincrement, (++std::declval<T&>()));
96
97 BOOST_HISTOGRAM_DETAIL_DETECT_BINARY(has_operator_equal, (std::declval<const T&>() ==
98 std::declval<const U>()));
99
100 BOOST_HISTOGRAM_DETAIL_DETECT_BINARY(has_operator_radd,
101 (std::declval<T&>() += std::declval<U>()));
102
103 BOOST_HISTOGRAM_DETAIL_DETECT_BINARY(has_operator_rsub,
104 (std::declval<T&>() -= std::declval<U>()));
105
106 BOOST_HISTOGRAM_DETAIL_DETECT_BINARY(has_operator_rmul,
107 (std::declval<T&>() *= std::declval<U>()));
108
109 BOOST_HISTOGRAM_DETAIL_DETECT_BINARY(has_operator_rdiv,
110 (std::declval<T&>() /= std::declval<U>()));
111
112 BOOST_HISTOGRAM_DETAIL_DETECT_BINARY(
113 has_method_eq, (std::declval<const T>().operator==(std::declval<const U>())));
114
115 BOOST_HISTOGRAM_DETAIL_DETECT(has_threading_support, (T::has_threading_support));
116
117 template <class T>
118 using is_storage = mp11::mp_and<is_indexable_container<T>, has_method_reset<T>,
119 has_threading_support<T>>;
120
121 template <class T>
122 using is_adaptible =
123 mp11::mp_and<mp11::mp_not<is_storage<T>>,
124 mp11::mp_or<is_vector_like<T>, is_array_like<T>, is_map_like<T>>>;
125
126 template <class T>
127 struct is_tuple_impl : mp11::mp_false {};
128
129 template <class... Ts>
130 struct is_tuple_impl<std::tuple<Ts...>> : mp11::mp_true {};
131
132 template <class T>
133 using is_tuple = typename is_tuple_impl<T>::type;
134
135 template <class T>
136 struct is_variant_impl : mp11::mp_false {};
137
138 template <class... Ts>
139 struct is_variant_impl<boost::variant2::variant<Ts...>> : mp11::mp_true {};
140
141 template <class T>
142 using is_variant = typename is_variant_impl<T>::type;
143
144 template <class T>
145 struct is_axis_variant_impl : mp11::mp_false {};
146
147 template <class... Ts>
148 struct is_axis_variant_impl<axis::variant<Ts...>> : mp11::mp_true {};
149
150 template <class T>
151 using is_axis_variant = typename is_axis_variant_impl<T>::type;
152
153 template <class T>
154 using is_any_axis = mp11::mp_or<is_axis<T>, is_axis_variant<T>>;
155
156 template <class T>
157 using is_sequence_of_axis = mp11::mp_and<is_iterable<T>, is_axis<mp11::mp_first<T>>>;
158
159 template <class T>
160 using is_sequence_of_axis_variant =
161 mp11::mp_and<is_iterable<T>, is_axis_variant<mp11::mp_first<T>>>;
162
163 template <class T>
164 using is_sequence_of_any_axis =
165 mp11::mp_and<is_iterable<T>, is_any_axis<mp11::mp_first<T>>>;
166
167 // poor-mans concept checks
168 template <class T, class = std::enable_if_t<is_storage<std::decay_t<T>>::value>>
169 struct requires_storage {};
170
171 template <class T, class _ = std::decay_t<T>,
172 class = std::enable_if_t<(is_storage<_>::value || is_adaptible<_>::value)>>
173 struct requires_storage_or_adaptible {};
174
175 template <class T, class = std::enable_if_t<is_iterator<std::decay_t<T>>::value>>
176 struct requires_iterator {};
177
178 template <class T, class = std::enable_if_t<
179 is_iterable<std::remove_cv_t<std::remove_reference_t<T>>>::value>>
180 struct requires_iterable {};
181
182 template <class T, class = std::enable_if_t<is_axis<std::decay_t<T>>::value>>
183 struct requires_axis {};
184
185 template <class T, class = std::enable_if_t<is_any_axis<std::decay_t<T>>::value>>
186 struct requires_any_axis {};
187
188 template <class T, class = std::enable_if_t<is_sequence_of_axis<std::decay_t<T>>::value>>
189 struct requires_sequence_of_axis {};
190
191 template <class T,
192 class = std::enable_if_t<is_sequence_of_axis_variant<std::decay_t<T>>::value>>
193 struct requires_sequence_of_axis_variant {};
194
195 template <class T,
196 class = std::enable_if_t<is_sequence_of_any_axis<std::decay_t<T>>::value>>
197 struct requires_sequence_of_any_axis {};
198
199 template <class T,
200 class = std::enable_if_t<is_any_axis<mp11::mp_first<std::decay_t<T>>>::value>>
201 struct requires_axes {};
202
203 template <class T, class U, class = std::enable_if_t<std::is_convertible<T, U>::value>>
204 struct requires_convertible {};
205
206 template <class T, class U,
207 class = std::enable_if_t<is_transform<std::decay_t<T>, U>::value>>
208 struct requires_transform {};
209
210 } // namespace detail
211 } // namespace histogram
212 } // namespace boost
213
214 #endif