Imported Upstream version 1.71.0
[platform/upstream/boost.git] / libs / histogram / test / detail_meta_test.cpp
1 // Copyright 2015-2017 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 #include <array>
8 #include <boost/core/lightweight_test.hpp>
9 #include <boost/core/lightweight_test_trait.hpp>
10 #include <boost/histogram/axis/integer.hpp>
11 #include <boost/histogram/axis/regular.hpp>
12 #include <boost/histogram/axis/variant.hpp>
13 #include <boost/histogram/detail/args_type.hpp>
14 #include <boost/histogram/detail/make_default.hpp>
15 #include <boost/histogram/histogram.hpp>
16 #include <boost/histogram/unlimited_storage.hpp>
17 #include <deque>
18 #include <iterator>
19 #include <map>
20 #include <tuple>
21 #include <type_traits>
22 #include <unordered_map>
23 #include <utility>
24 #include <vector>
25 #include "throw_exception.hpp"
26 #include "utility_allocator.hpp"
27 #include "std_ostream.hpp"
28
29 using namespace boost::histogram;
30 using namespace boost::histogram::detail;
31
32 int main() {
33   // has_method_value*
34   {
35     struct A {};
36     struct B {
37       A value(int) const { return {}; }
38     };
39     struct C {
40       char value(int) const { return 0; }
41     };
42
43     BOOST_TEST_TRAIT_FALSE((has_method_value<A>));
44     BOOST_TEST_TRAIT_TRUE((has_method_value<B>));
45     BOOST_TEST_TRAIT_TRUE((has_method_value<C>));
46   }
47
48   // has_method_options
49   {
50     struct A {};
51     struct B {
52       void options() {}
53     };
54
55     BOOST_TEST_TRAIT_FALSE((has_method_options<A>));
56     BOOST_TEST_TRAIT_TRUE((has_method_options<B>));
57   }
58
59   // has_method_metadata
60   {
61     struct A {};
62     struct B {
63       void metadata();
64     };
65
66     BOOST_TEST_TRAIT_FALSE((has_method_metadata<A>));
67     BOOST_TEST_TRAIT_TRUE((has_method_metadata<B>));
68   }
69
70   // has_method_update
71   {
72     struct A {};
73     struct B {
74       void update(int) {}
75     };
76     using C = axis::integer<int, axis::null_type, use_default>;
77
78     BOOST_TEST_TRAIT_FALSE((has_method_update<A>));
79     BOOST_TEST_TRAIT_TRUE((has_method_update<B>));
80     BOOST_TEST_TRAIT_TRUE((has_method_update<C>));
81   }
82
83   // has_method_resize
84   {
85     struct A {};
86     using B = std::vector<int>;
87     using C = std::map<int, int>;
88
89     BOOST_TEST_TRAIT_FALSE((has_method_resize<A>));
90     BOOST_TEST_TRAIT_TRUE((has_method_resize<B>));
91     BOOST_TEST_TRAIT_FALSE((has_method_resize<C>));
92   }
93
94   // has_method_size
95   {
96     struct A {};
97     using B = std::vector<int>;
98     using C = std::map<int, int>;
99
100     BOOST_TEST_TRAIT_FALSE((has_method_size<A>));
101     BOOST_TEST_TRAIT_TRUE((has_method_size<B>));
102     BOOST_TEST_TRAIT_TRUE((has_method_size<C>));
103   }
104
105   // has_method_clear
106   {
107     struct A {};
108     using B = std::vector<int>;
109     using C = std::map<int, int>;
110     using D = std::array<int, 10>;
111
112     BOOST_TEST_TRAIT_FALSE((has_method_clear<A>));
113     BOOST_TEST_TRAIT_TRUE((has_method_clear<B>));
114     BOOST_TEST_TRAIT_TRUE((has_method_clear<C>));
115     BOOST_TEST_TRAIT_FALSE((has_method_clear<D>));
116   }
117
118   // has_allocator
119   {
120     struct A {};
121     using B = std::vector<int>;
122     using C = std::map<int, int>;
123     using D = std::array<int, 10>;
124
125     BOOST_TEST_TRAIT_FALSE((has_method_clear<A>));
126     BOOST_TEST_TRAIT_TRUE((has_method_clear<B>));
127     BOOST_TEST_TRAIT_TRUE((has_method_clear<C>));
128     BOOST_TEST_TRAIT_FALSE((has_method_clear<D>));
129   }
130
131   // is_storage
132   {
133     struct A {};
134     using B = std::vector<int>;
135     using C = unlimited_storage<>;
136
137     BOOST_TEST_TRAIT_FALSE((is_storage<A>));
138     BOOST_TEST_TRAIT_FALSE((is_storage<B>));
139     BOOST_TEST_TRAIT_TRUE((is_storage<C>));
140   }
141
142   // is_indexable
143   {
144     struct A {};
145     using B = std::vector<int>;
146     using C = std::map<int, int>;
147     using D = std::map<A, int>;
148
149     BOOST_TEST_TRAIT_FALSE((is_indexable<A>));
150     BOOST_TEST_TRAIT_TRUE((is_indexable<B>));
151     BOOST_TEST_TRAIT_TRUE((is_indexable<C>));
152     BOOST_TEST_TRAIT_FALSE((is_indexable<D>));
153   }
154
155   // is_transform
156   {
157     struct A {};
158     struct B {
159       double forward(double);
160       double inverse(double);
161     };
162
163     BOOST_TEST_TRAIT_FALSE((is_transform<A>));
164     BOOST_TEST_TRAIT_TRUE((is_transform<B>));
165   }
166
167   // is_vector_like
168   {
169     struct A {};
170     using B = std::vector<int>;
171     using C = std::array<int, 10>;
172     using D = std::map<unsigned, int>;
173     using E = std::deque<int>;
174     BOOST_TEST_TRAIT_FALSE((is_vector_like<A>));
175     BOOST_TEST_TRAIT_TRUE((is_vector_like<B>));
176     BOOST_TEST_TRAIT_FALSE((is_vector_like<C>));
177     BOOST_TEST_TRAIT_FALSE((is_vector_like<D>));
178     BOOST_TEST_TRAIT_TRUE((is_vector_like<E>));
179   }
180
181   // is_array_like
182   {
183     struct A {};
184     using B = std::vector<int>;
185     using C = std::array<int, 10>;
186     using D = std::map<unsigned, int>;
187     BOOST_TEST_TRAIT_FALSE((is_array_like<A>));
188     BOOST_TEST_TRAIT_FALSE((is_array_like<B>));
189     BOOST_TEST_TRAIT_TRUE((is_array_like<C>));
190     BOOST_TEST_TRAIT_FALSE((is_array_like<D>));
191   }
192
193   // is_map_like
194   {
195     struct A {};
196     using B = std::vector<int>;
197     using C = std::array<int, 10>;
198     using D = std::map<unsigned, int>;
199     using E = std::unordered_map<unsigned, int>;
200     BOOST_TEST_TRAIT_FALSE((is_map_like<A>));
201     BOOST_TEST_TRAIT_FALSE((is_map_like<B>));
202     BOOST_TEST_TRAIT_FALSE((is_map_like<C>));
203     BOOST_TEST_TRAIT_TRUE((is_map_like<D>));
204     BOOST_TEST_TRAIT_TRUE((is_map_like<E>));
205   }
206
207   // is_axis
208   {
209     struct A {};
210     struct B {
211       int index(double);
212       int size() const;
213     };
214     struct C {
215       int index(double);
216     };
217     struct D {
218       int size();
219     };
220     using E = axis::variant<axis::regular<>>;
221
222     BOOST_TEST_TRAIT_FALSE((is_axis<A>));
223     BOOST_TEST_TRAIT_TRUE((is_axis<B>));
224     BOOST_TEST_TRAIT_FALSE((is_axis<C>));
225     BOOST_TEST_TRAIT_FALSE((is_axis<D>));
226     BOOST_TEST_TRAIT_FALSE((is_axis<E>));
227   }
228
229   // is_iterable
230   {
231     using A = std::vector<int>;
232     using B = int[3];
233     using C = std::initializer_list<int>;
234     BOOST_TEST_TRAIT_FALSE((is_iterable<int>));
235     BOOST_TEST_TRAIT_TRUE((is_iterable<A>));
236     BOOST_TEST_TRAIT_TRUE((is_iterable<B>));
237     BOOST_TEST_TRAIT_TRUE((is_iterable<C>));
238   }
239
240   // is_streamable
241   {
242     struct Foo {};
243     BOOST_TEST_TRAIT_TRUE((is_streamable<int>));
244     BOOST_TEST_TRAIT_TRUE((is_streamable<std::string>));
245     BOOST_TEST_TRAIT_FALSE((is_streamable<Foo>));
246   }
247
248   // is_axis_variant
249   {
250     struct A {};
251     BOOST_TEST_TRAIT_FALSE((is_axis_variant<A>));
252     BOOST_TEST_TRAIT_TRUE((is_axis_variant<axis::variant<>>));
253     BOOST_TEST_TRAIT_TRUE((is_axis_variant<axis::variant<axis::regular<>>>));
254   }
255
256   // args_type, arg_type
257   {
258     struct Foo {
259       static int f1(char);
260       int f2(long) const;
261     };
262
263     BOOST_TEST_TRAIT_SAME(args_type<decltype(&Foo::f1)>, std::tuple<char>);
264     BOOST_TEST_TRAIT_SAME(args_type<decltype(&Foo::f2)>, std::tuple<long>);
265     BOOST_TEST_TRAIT_SAME(arg_type<decltype(&Foo::f1)>, char);
266     BOOST_TEST_TRAIT_SAME(arg_type<decltype(&Foo::f2)>, long);
267   }
268
269   // static_if
270   {
271     struct callable {
272       int operator()() { return 1; };
273     };
274     struct not_callable {};
275     auto fcn = [](auto b, auto x) {
276       return static_if<decltype(b)>([](auto x) { return x(); }, [](auto) { return 2; },
277                                     x);
278     };
279     BOOST_TEST_EQ(fcn(std::true_type(), callable()), 1);
280     BOOST_TEST_EQ(fcn(std::false_type(), not_callable()), 2);
281   }
282
283   // tuple_slice
284   {
285     auto a = std::make_tuple(1, 2, 3, 4);
286     auto b = tuple_slice<1, 2>(a);
287     BOOST_TEST_EQ(b, std::make_tuple(2, 3));
288   }
289
290   // is_sequence_of_axis
291   {
292     using A = std::vector<axis::regular<>>;
293     using B = std::vector<axis::variant<axis::regular<>>>;
294     using C = std::vector<int>;
295     auto v = std::vector<axis::variant<axis::regular<>, axis::integer<>>>();
296     BOOST_TEST_TRAIT_TRUE((is_sequence_of_any_axis<A>));
297     BOOST_TEST_TRAIT_TRUE((is_sequence_of_axis<A>));
298     BOOST_TEST_TRAIT_FALSE((is_sequence_of_axis_variant<A>));
299     BOOST_TEST_TRAIT_TRUE((is_sequence_of_any_axis<B>));
300     BOOST_TEST_TRAIT_TRUE((is_sequence_of_axis_variant<B>));
301     BOOST_TEST_TRAIT_FALSE((is_sequence_of_axis<B>));
302     BOOST_TEST_TRAIT_FALSE((is_sequence_of_any_axis<C>));
303     BOOST_TEST_TRAIT_TRUE((is_sequence_of_any_axis<decltype(v)>));
304   }
305
306   // is_weight
307   {
308     struct A {};
309     using B = int;
310     using C = decltype(weight(1));
311     BOOST_TEST_TRAIT_FALSE((is_weight<A>));
312     BOOST_TEST_TRAIT_FALSE((is_weight<B>));
313     BOOST_TEST_TRAIT_TRUE((is_weight<C>));
314   }
315
316   // is_sample
317   {
318     struct A {};
319     using B = int;
320     using C = decltype(sample(1));
321     using D = decltype(sample(1, 2.0));
322     BOOST_TEST_TRAIT_FALSE((is_sample<A>));
323     BOOST_TEST_TRAIT_FALSE((is_sample<B>));
324     BOOST_TEST_TRAIT_TRUE((is_sample<C>));
325     BOOST_TEST_TRAIT_TRUE((is_sample<D>));
326   }
327
328   // make_default
329   {
330     struct A {};
331     auto a = make_default(A());
332     BOOST_TEST_TRAIT_SAME(decltype(a), A);
333     tracing_allocator_db db;
334     using B = std::vector<int, tracing_allocator<int>>;
335     B b = make_default(B(tracing_allocator<int>(db)));
336     b.resize(100);
337     BOOST_TEST_EQ(db.at<int>().first, 100);
338   }
339
340   // has_operator_equal
341   {
342     struct A {};
343     struct B {
344       bool operator==(const B&) const { return true; }
345     };
346
347     BOOST_TEST_TRAIT_FALSE((has_operator_equal<A, A>));
348     BOOST_TEST_TRAIT_FALSE((has_operator_equal<B, A>));
349     BOOST_TEST_TRAIT_TRUE((has_operator_equal<B, B>));
350     BOOST_TEST_TRAIT_TRUE((has_operator_equal<const B&, const B&>));
351   }
352
353   // has_operator_radd
354   {
355     struct A {};
356     struct B {
357       B& operator+=(const B&) { return *this; }
358     };
359
360     BOOST_TEST_TRAIT_FALSE((has_operator_radd<A, A>));
361     BOOST_TEST_TRAIT_FALSE((has_operator_radd<B, A>));
362     BOOST_TEST_TRAIT_TRUE((has_operator_radd<B, B>));
363     BOOST_TEST_TRAIT_TRUE((has_operator_radd<B&, const B&>));
364   }
365
366   return boost::report_errors();
367 }