]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/histogram/detail/detect.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / histogram / detail / detect.hpp
CommitLineData
92f5a8d4
TL
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>
20effc67
TL
11#include <boost/mp11/function.hpp> // mp_and, mp_or
12#include <boost/mp11/integral.hpp> // mp_not
13#include <boost/mp11/list.hpp> // mp_first
92f5a8d4
TL
14#include <iterator>
15#include <tuple>
16#include <type_traits>
17
f67539c2
TL
18// forward declaration
19namespace boost {
20namespace variant2 {
21template <class...>
22class variant;
23} // namespace variant2
24} // namespace boost
25
92f5a8d4
TL
26namespace boost {
27namespace histogram {
28namespace detail {
29
20effc67
TL
30#define BOOST_HISTOGRAM_DETAIL_DETECT(name, cond) \
31 template <class U> \
32 struct name##_impl { \
33 typedef char yes[1]; \
34 typedef char no[2]; \
35 template <class T> \
36 static yes& test(T& t, decltype(cond, 0)); \
37 template <class T> \
38 static no& test(T&, float); \
39 using type = \
40 std::integral_constant<bool, (sizeof(test(std::declval<U&>(), 0)) == 1)>; \
41 }; \
42 template <class T> \
43 using name = typename name##_impl<T>::type
44
45#define BOOST_HISTOGRAM_DETAIL_DETECT_BINARY(name, cond) \
46 template <class V, class W> \
47 struct name##_impl { \
48 typedef char yes[1]; \
49 typedef char no[2]; \
50 template <class T, class U> \
51 static yes& test(decltype(cond, 0)); \
52 template <class, class> \
53 static no& test(float); \
54 using type = std::integral_constant<bool, (sizeof(test<V, W>(0)) == 1)>; \
55 }; \
56 template <class T, class U = T> \
57 using name = typename name##_impl<T, U>::type
92f5a8d4
TL
58
59// reset has overloads, trying to get pmf in this case always fails
20effc67 60BOOST_HISTOGRAM_DETAIL_DETECT(has_method_reset, t.reset(0));
92f5a8d4 61
20effc67 62BOOST_HISTOGRAM_DETAIL_DETECT(is_indexable, t[0]);
92f5a8d4
TL
63
64BOOST_HISTOGRAM_DETAIL_DETECT_BINARY(
65 is_transform,
66 (std::declval<T&>().inverse(std::declval<T&>().forward(std::declval<U>()))));
67
20effc67
TL
68BOOST_HISTOGRAM_DETAIL_DETECT(is_indexable_container,
69 (t[0], t.size(), std::begin(t), std::end(t)));
92f5a8d4
TL
70
71BOOST_HISTOGRAM_DETAIL_DETECT(is_vector_like,
20effc67 72 (t[0], t.size(), t.resize(0), std::begin(t), std::end(t)));
92f5a8d4 73
20effc67
TL
74BOOST_HISTOGRAM_DETAIL_DETECT(is_array_like, (t[0], t.size(), std::tuple_size<T>::value,
75 std::begin(t), std::end(t)));
92f5a8d4 76
20effc67
TL
77BOOST_HISTOGRAM_DETAIL_DETECT(is_map_like, ((typename T::key_type*)nullptr,
78 (typename T::mapped_type*)nullptr,
79 std::begin(t), std::end(t)));
92f5a8d4
TL
80
81// ok: is_axis is false for axis::variant, because T::index is templated
20effc67 82BOOST_HISTOGRAM_DETAIL_DETECT(is_axis, (t.size(), &T::index));
92f5a8d4 83
20effc67 84BOOST_HISTOGRAM_DETAIL_DETECT(is_iterable, (std::begin(t), std::end(t)));
92f5a8d4
TL
85
86BOOST_HISTOGRAM_DETAIL_DETECT(is_iterator,
20effc67 87 (typename std::iterator_traits<T>::iterator_category{}));
92f5a8d4 88
20effc67 89BOOST_HISTOGRAM_DETAIL_DETECT(is_streamable, (std::declval<std::ostream&>() << t));
92f5a8d4 90
20effc67 91BOOST_HISTOGRAM_DETAIL_DETECT(has_operator_preincrement, ++t);
92f5a8d4
TL
92
93BOOST_HISTOGRAM_DETAIL_DETECT_BINARY(has_operator_equal, (std::declval<const T&>() ==
20effc67 94 std::declval<const U&>()));
92f5a8d4
TL
95
96BOOST_HISTOGRAM_DETAIL_DETECT_BINARY(has_operator_radd,
97 (std::declval<T&>() += std::declval<U>()));
98
99BOOST_HISTOGRAM_DETAIL_DETECT_BINARY(has_operator_rsub,
100 (std::declval<T&>() -= std::declval<U>()));
101
102BOOST_HISTOGRAM_DETAIL_DETECT_BINARY(has_operator_rmul,
103 (std::declval<T&>() *= std::declval<U>()));
104
105BOOST_HISTOGRAM_DETAIL_DETECT_BINARY(has_operator_rdiv,
106 (std::declval<T&>() /= std::declval<U>()));
107
108BOOST_HISTOGRAM_DETAIL_DETECT_BINARY(
20effc67 109 has_method_eq, (std::declval<const T&>().operator==(std::declval<const U&>())));
92f5a8d4
TL
110
111BOOST_HISTOGRAM_DETAIL_DETECT(has_threading_support, (T::has_threading_support));
112
113template <class T>
114using is_storage = mp11::mp_and<is_indexable_container<T>, has_method_reset<T>,
115 has_threading_support<T>>;
116
117template <class T>
118using is_adaptible =
119 mp11::mp_and<mp11::mp_not<is_storage<T>>,
120 mp11::mp_or<is_vector_like<T>, is_array_like<T>, is_map_like<T>>>;
121
122template <class T>
20effc67 123struct is_tuple_impl : std::false_type {};
92f5a8d4
TL
124
125template <class... Ts>
20effc67 126struct is_tuple_impl<std::tuple<Ts...>> : std::true_type {};
92f5a8d4
TL
127
128template <class T>
129using is_tuple = typename is_tuple_impl<T>::type;
130
131template <class T>
20effc67 132struct is_variant_impl : std::false_type {};
92f5a8d4
TL
133
134template <class... Ts>
20effc67 135struct is_variant_impl<boost::variant2::variant<Ts...>> : std::true_type {};
92f5a8d4
TL
136
137template <class T>
138using is_variant = typename is_variant_impl<T>::type;
139
140template <class T>
20effc67 141struct is_axis_variant_impl : std::false_type {};
92f5a8d4
TL
142
143template <class... Ts>
20effc67 144struct is_axis_variant_impl<axis::variant<Ts...>> : std::true_type {};
92f5a8d4
TL
145
146template <class T>
147using is_axis_variant = typename is_axis_variant_impl<T>::type;
148
149template <class T>
150using is_any_axis = mp11::mp_or<is_axis<T>, is_axis_variant<T>>;
151
152template <class T>
153using is_sequence_of_axis = mp11::mp_and<is_iterable<T>, is_axis<mp11::mp_first<T>>>;
154
155template <class T>
156using is_sequence_of_axis_variant =
157 mp11::mp_and<is_iterable<T>, is_axis_variant<mp11::mp_first<T>>>;
158
159template <class T>
160using is_sequence_of_any_axis =
161 mp11::mp_and<is_iterable<T>, is_any_axis<mp11::mp_first<T>>>;
162
163// poor-mans concept checks
164template <class T, class = std::enable_if_t<is_storage<std::decay_t<T>>::value>>
165struct requires_storage {};
166
167template <class T, class _ = std::decay_t<T>,
168 class = std::enable_if_t<(is_storage<_>::value || is_adaptible<_>::value)>>
169struct requires_storage_or_adaptible {};
170
171template <class T, class = std::enable_if_t<is_iterator<std::decay_t<T>>::value>>
172struct requires_iterator {};
173
174template <class T, class = std::enable_if_t<
175 is_iterable<std::remove_cv_t<std::remove_reference_t<T>>>::value>>
176struct requires_iterable {};
177
178template <class T, class = std::enable_if_t<is_axis<std::decay_t<T>>::value>>
179struct requires_axis {};
180
181template <class T, class = std::enable_if_t<is_any_axis<std::decay_t<T>>::value>>
182struct requires_any_axis {};
183
184template <class T, class = std::enable_if_t<is_sequence_of_axis<std::decay_t<T>>::value>>
185struct requires_sequence_of_axis {};
186
187template <class T,
188 class = std::enable_if_t<is_sequence_of_axis_variant<std::decay_t<T>>::value>>
189struct requires_sequence_of_axis_variant {};
190
191template <class T,
192 class = std::enable_if_t<is_sequence_of_any_axis<std::decay_t<T>>::value>>
193struct requires_sequence_of_any_axis {};
194
195template <class T,
196 class = std::enable_if_t<is_any_axis<mp11::mp_first<std::decay_t<T>>>::value>>
197struct requires_axes {};
198
92f5a8d4
TL
199template <class T, class U,
200 class = std::enable_if_t<is_transform<std::decay_t<T>, U>::value>>
201struct requires_transform {};
202
203} // namespace detail
204} // namespace histogram
205} // namespace boost
206
207#endif