1 // Copyright 2015-2017 Hans Dembinski
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)
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>
21 #include <type_traits>
22 #include <unordered_map>
25 #include "throw_exception.hpp"
26 #include "utility_allocator.hpp"
27 #include "std_ostream.hpp"
29 using namespace boost::histogram;
30 using namespace boost::histogram::detail;
37 A value(int) const { return {}; }
40 char value(int) const { return 0; }
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>));
55 BOOST_TEST_TRAIT_FALSE((has_method_options<A>));
56 BOOST_TEST_TRAIT_TRUE((has_method_options<B>));
59 // has_method_metadata
66 BOOST_TEST_TRAIT_FALSE((has_method_metadata<A>));
67 BOOST_TEST_TRAIT_TRUE((has_method_metadata<B>));
76 using C = axis::integer<int, axis::null_type, use_default>;
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>));
86 using B = std::vector<int>;
87 using C = std::map<int, int>;
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>));
97 using B = std::vector<int>;
98 using C = std::map<int, int>;
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>));
108 using B = std::vector<int>;
109 using C = std::map<int, int>;
110 using D = std::array<int, 10>;
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>));
121 using B = std::vector<int>;
122 using C = std::map<int, int>;
123 using D = std::array<int, 10>;
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>));
134 using B = std::vector<int>;
135 using C = unlimited_storage<>;
137 BOOST_TEST_TRAIT_FALSE((is_storage<A>));
138 BOOST_TEST_TRAIT_FALSE((is_storage<B>));
139 BOOST_TEST_TRAIT_TRUE((is_storage<C>));
145 using B = std::vector<int>;
146 using C = std::map<int, int>;
147 using D = std::map<A, int>;
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>));
159 double forward(double);
160 double inverse(double);
163 BOOST_TEST_TRAIT_FALSE((is_transform<A>));
164 BOOST_TEST_TRAIT_TRUE((is_transform<B>));
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>));
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>));
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>));
220 using E = axis::variant<axis::regular<>>;
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>));
231 using A = std::vector<int>;
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>));
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>));
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<>>>));
256 // args_type, arg_type
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);
272 int operator()() { return 1; };
274 struct not_callable {};
275 auto fcn = [](auto b, auto x) {
276 return static_if<decltype(b)>([](auto x) { return x(); }, [](auto) { return 2; },
279 BOOST_TEST_EQ(fcn(std::true_type(), callable()), 1);
280 BOOST_TEST_EQ(fcn(std::false_type(), not_callable()), 2);
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));
290 // is_sequence_of_axis
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)>));
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>));
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>));
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)));
337 BOOST_TEST_EQ(db.at<int>().first, 100);
340 // has_operator_equal
344 bool operator==(const B&) const { return true; }
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&>));
357 B& operator+=(const B&) { return *this; }
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&>));
366 return boost::report_errors();