• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 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 <boost/core/lightweight_test.hpp>
8 #include <boost/core/lightweight_test_trait.hpp>
9 #include <boost/histogram/axis.hpp>
10 #include <boost/histogram/axis/traits.hpp>
11 #include "std_ostream.hpp"
12 #include "throw_exception.hpp"
13 #include "utility_axis.hpp"
14 
15 using namespace boost::histogram::axis;
16 using namespace std::literals;
17 
18 struct ValueTypeOverride {
19   index_type index(int);
20 };
21 
22 namespace boost {
23 namespace histogram {
24 namespace detail {
25 template <>
26 struct value_type_deducer<ValueTypeOverride> {
27   using type = char;
28 };
29 } // namespace detail
30 } // namespace histogram
31 } // namespace boost
32 
main()33 int main() {
34   // value_type
35   {
36     struct Foo {
37       void index(const long&);
38     };
39 
40     BOOST_TEST_TRAIT_SAME(traits::value_type<Foo>, long);
41     BOOST_TEST_TRAIT_SAME(traits::value_type<ValueTypeOverride>, char);
42     BOOST_TEST_TRAIT_SAME(traits::value_type<integer<int>>, int);
43     BOOST_TEST_TRAIT_SAME(traits::value_type<category<int>>, int);
44     BOOST_TEST_TRAIT_SAME(traits::value_type<regular<double>>, double);
45   }
46 
47   // is_continuous
48   {
49     BOOST_TEST_TRAIT_TRUE((traits::is_continuous<regular<>>));
50     BOOST_TEST_TRAIT_FALSE((traits::is_continuous<integer<int>>));
51     BOOST_TEST_TRAIT_FALSE((traits::is_continuous<category<int>>));
52     BOOST_TEST_TRAIT_TRUE((traits::is_continuous<integer<double>>));
53   }
54 
55   // is_reducible
56   {
57     struct not_reducible {};
58     struct reducible {
59       reducible(const reducible&, index_type, index_type, unsigned);
60     };
61 
62     BOOST_TEST_TRAIT_TRUE((traits::is_reducible<reducible>));
63     BOOST_TEST_TRAIT_FALSE((traits::is_reducible<not_reducible>));
64 
65     BOOST_TEST_TRAIT_TRUE((traits::is_reducible<regular<>>));
66     BOOST_TEST_TRAIT_TRUE((traits::is_reducible<variable<>>));
67     BOOST_TEST_TRAIT_TRUE((traits::is_reducible<circular<>>));
68     BOOST_TEST_TRAIT_TRUE((traits::is_reducible<integer<>>));
69     BOOST_TEST_TRAIT_TRUE((traits::is_reducible<category<>>));
70   }
71 
72   // get_options, options()
73   {
74     using A = integer<>;
75     BOOST_TEST_EQ(traits::get_options<A>::test(option::growth), false);
76     auto expected = option::underflow | option::overflow;
77     auto a = A{};
78     BOOST_TEST_EQ(traits::options(a), expected);
79     BOOST_TEST_EQ(traits::options(static_cast<A&>(a)), expected);
80     BOOST_TEST_EQ(traits::options(static_cast<const A&>(a)), expected);
81     BOOST_TEST_EQ(traits::options(std::move(a)), expected);
82 
83     using B = integer<int, null_type, option::growth_t>;
84     BOOST_TEST_EQ(traits::get_options<B>::test(option::growth), true);
85     BOOST_TEST_EQ(traits::options(B{}), option::growth);
86 
87     struct growing {
88       auto update(double) { return std::make_pair(0, 0); }
89     };
90     using C = growing;
91     BOOST_TEST_EQ(traits::get_options<C>::test(option::growth), true);
92     auto c = C{};
93     BOOST_TEST_EQ(traits::options(c), option::growth);
94     BOOST_TEST_EQ(traits::options(static_cast<C&>(c)), option::growth);
95     BOOST_TEST_EQ(traits::options(static_cast<const C&>(c)), option::growth);
96     BOOST_TEST_EQ(traits::options(std::move(c)), option::growth);
97 
98     struct notgrowing {
99       auto index(double) { return 0; }
100     };
101     using D = notgrowing;
102     BOOST_TEST_EQ(traits::get_options<D>::test(option::growth), false);
103     auto d = D{};
104     BOOST_TEST_EQ(traits::options(d), option::none);
105     BOOST_TEST_EQ(traits::options(static_cast<D&>(d)), option::none);
106     BOOST_TEST_EQ(traits::options(static_cast<const D&>(d)), option::none);
107     BOOST_TEST_EQ(traits::options(std::move(d)), option::none);
108   }
109 
110   // is_inclusive, inclusive()
111   {
112     struct empty {};
113     struct with_opts_not_inclusive {
114       static constexpr unsigned options() { return option::underflow | option::overflow; }
115       static constexpr bool inclusive() { return false; }
116     };
117 
118     BOOST_TEST_EQ(traits::inclusive(empty{}), false);
119     BOOST_TEST_EQ(traits::inclusive(regular<>{}), true);
120 
121     BOOST_TEST_TRAIT_FALSE((traits::is_inclusive<empty>));
122     BOOST_TEST_TRAIT_FALSE((traits::is_inclusive<with_opts_not_inclusive>));
123 
124     BOOST_TEST_TRAIT_TRUE((traits::is_inclusive<regular<>>));
125     BOOST_TEST_TRAIT_FALSE(
126         (traits::is_inclusive<
127             regular<double, boost::use_default, boost::use_default, option::growth_t>>));
128     BOOST_TEST_TRAIT_FALSE(
129         (traits::is_inclusive<regular<double, boost::use_default, boost::use_default,
130                                       option::circular_t>>));
131 
132     BOOST_TEST_TRAIT_TRUE((traits::is_inclusive<variable<>>));
133     BOOST_TEST_TRAIT_FALSE(
134         (traits::is_inclusive<variable<double, boost::use_default, option::growth_t>>));
135     BOOST_TEST_TRAIT_FALSE(
136         (traits::is_inclusive<variable<double, boost::use_default, option::circular_t>>));
137 
138     BOOST_TEST_TRAIT_TRUE((traits::is_inclusive<integer<int>>));
139     BOOST_TEST_TRAIT_TRUE(
140         (traits::is_inclusive<integer<int, boost::use_default, option::growth_t>>));
141     BOOST_TEST_TRAIT_TRUE(
142         (traits::is_inclusive<integer<int, boost::use_default, option::circular_t>>));
143 
144     BOOST_TEST_TRAIT_TRUE((traits::is_inclusive<integer<double>>));
145     BOOST_TEST_TRAIT_FALSE(
146         (traits::is_inclusive<integer<double, boost::use_default, option::growth_t>>));
147     BOOST_TEST_TRAIT_FALSE(
148         (traits::is_inclusive<integer<double, boost::use_default, option::circular_t>>));
149 
150     BOOST_TEST_TRAIT_TRUE((traits::is_inclusive<category<int>>));
151     BOOST_TEST_TRAIT_TRUE(
152         (traits::is_inclusive<category<int, boost::use_default, option::growth_t>>));
153     BOOST_TEST_TRAIT_FALSE(
154         (traits::is_inclusive<category<int, boost::use_default, option::none_t>>));
155   }
156 
157   // is_ordered, ordered()
158   {
159     struct ordered_1 {
160       constexpr static bool ordered() { return true; }
161       index_type index(ordered_1) { return true; }
162     };
163     struct ordered_2 {
164       index_type index(int);
165     };
166     struct not_ordered_1 {
167       constexpr static bool ordered() { return false; }
168       index_type index(int);
169     };
170     struct not_ordered_2 {
171       index_type index(not_ordered_2);
172     };
173 
174     BOOST_TEST_TRAIT_TRUE((traits::is_ordered<ordered_1>));
175     BOOST_TEST_TRAIT_TRUE((traits::is_ordered<ordered_2>));
176     BOOST_TEST_TRAIT_FALSE((traits::is_ordered<not_ordered_1>));
177     BOOST_TEST_TRAIT_FALSE((traits::is_ordered<not_ordered_2>));
178 
179     BOOST_TEST(traits::ordered(integer<>{}));
180     BOOST_TEST_NOT(traits::ordered(category<int>{}));
181   }
182 
183   // index, rank, value, width
184   {
185     auto a = integer<>(1, 3);
186     BOOST_TEST_EQ(traits::index(a, 1), 0);
187     BOOST_TEST_EQ(traits::rank(a), 1);
188     BOOST_TEST_EQ(traits::value(a, 0), 1);
189     BOOST_TEST_EQ(traits::width(a, 0), 0);
190     BOOST_TEST_EQ(traits::width(a, 0), 0);
191 
192     auto b = integer<double>(1, 3);
193     BOOST_TEST_EQ(traits::index(b, 1), 0);
194     BOOST_TEST_EQ(traits::rank(b), 1);
195     BOOST_TEST_EQ(traits::value(b, 0), 1);
196     BOOST_TEST_EQ(traits::width(b, 0), 1);
197     BOOST_TEST(traits::get_options<decltype(b)>::test(option::underflow));
198 
199     auto c = category<std::string>{"red", "blue"};
200     BOOST_TEST_EQ(traits::index(c, "blue"), 1);
201     BOOST_TEST_EQ(traits::rank(c), 1);
202     BOOST_TEST_EQ(traits::value(c, 0), "red"s);
203     BOOST_TEST_EQ(traits::width(c, 0), 0);
204 
205     struct D {
206       index_type index(const std::tuple<int, double>& args) const {
207         return static_cast<index_type>(std::get<0>(args) + std::get<1>(args));
208       }
209       index_type size() const { return 5; }
210     } d;
211     BOOST_TEST_EQ(traits::index(d, std::make_tuple(1, 2.0)), 3.0);
212     BOOST_TEST_EQ(traits::rank(d), 2u);
213 
214     variant<D, integer<>> v;
215     v = a;
216     BOOST_TEST_EQ(traits::rank(v), 1u);
217     v = d;
218     BOOST_TEST_EQ(traits::rank(v), 2u);
219 
220     struct E : integer<> {
221       using integer::integer; // inherit ctors of base
222       // customization point: convert argument and call base class
223       auto index(const char* s) const { return integer::index(std::atoi(s)); }
224     };
225 
226     BOOST_TEST_EQ(traits::index(E{0, 3}, "2"), 2);
227   }
228 
229   // update
230   {
231     auto a = integer<int, null_type, option::growth_t>();
232     BOOST_TEST_EQ(traits::update(a, 0), (std::pair<index_type, index_type>(0, -1)));
233     BOOST_TEST_THROWS(traits::update(a, "foo"), std::invalid_argument);
234 
235     variant<integer<int, null_type, option::growth_t>, integer<>> v(a);
236     BOOST_TEST_EQ(traits::update(v, 0), (std::pair<index_type, index_type>(0, 0)));
237   }
238 
239   // metadata
240   {
241     struct None {};
242 
243     struct Const {
244       const int& metadata() const { return m; };
245       int m = 0;
246     };
247 
248     struct Both {
249       const int& metadata() const { return m; };
250       int& metadata() { return m; };
251       int m = 0;
252     };
253 
254     None none;
255     BOOST_TEST_TRAIT_SAME(decltype(traits::metadata(none)), null_type&);
256     BOOST_TEST_TRAIT_SAME(decltype(traits::metadata(static_cast<None&>(none))),
257                           null_type&);
258     BOOST_TEST_TRAIT_SAME(decltype(traits::metadata(static_cast<const None&>(none))),
259                           null_type&);
260 
261     Const c;
262     BOOST_TEST_EQ(traits::metadata(c), 0);
263     BOOST_TEST_EQ(traits::metadata(static_cast<Const&>(c)), 0);
264     BOOST_TEST_EQ(traits::metadata(static_cast<const Const&>(c)), 0);
265 
266     Both b;
267     BOOST_TEST_EQ(traits::metadata(b), 0);
268     BOOST_TEST_EQ(traits::metadata(static_cast<Both&>(b)), 0);
269     BOOST_TEST_EQ(traits::metadata(static_cast<const Both&>(b)), 0);
270   }
271 
272   return boost::report_errors();
273 }
274