1 // Copyright 2015-2018 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)
7 #include <boost/core/ignore_unused.hpp>
8 #include <boost/core/lightweight_test.hpp>
9 #include <boost/core/lightweight_test_trait.hpp>
10 #include <boost/histogram/axis/category.hpp>
11 #include <boost/histogram/axis/ostream.hpp>
12 #include <boost/histogram/axis/traits.hpp>
16 #include <type_traits>
17 #include "std_ostream.hpp"
18 #include "throw_exception.hpp"
19 #include "utility_axis.hpp"
20 #include "utility_str.hpp"
23 using namespace boost::histogram;
25 BOOST_TEST(std::is_nothrow_move_constructible<axis::category<int>>::value);
26 BOOST_TEST(std::is_nothrow_move_constructible<axis::category<std::string>>::value);
27 BOOST_TEST(std::is_nothrow_move_assignable<axis::category<int>>::value);
28 BOOST_TEST(std::is_nothrow_move_assignable<axis::category<std::string>>::value);
33 boost::ignore_unused(x);
34 BOOST_TEST_THROWS(axis::category<int>(x + 1, x), std::invalid_argument);
37 // value should return copy for arithmetic types and const reference otherwise
39 enum class Foo { foo };
41 BOOST_TEST_TRAIT_SAME(axis::traits::value_type<axis::category<std::string>>,
43 BOOST_TEST_TRAIT_SAME(decltype(std::declval<axis::category<std::string>>().value(0)),
45 BOOST_TEST_TRAIT_SAME(axis::traits::value_type<axis::category<const char*>>,
47 BOOST_TEST_TRAIT_SAME(decltype(std::declval<axis::category<const char*>>().value(0)),
49 BOOST_TEST_TRAIT_SAME(axis::traits::value_type<axis::category<Foo>>, Foo);
50 BOOST_TEST_TRAIT_SAME(decltype(std::declval<axis::category<Foo>>().value(0)), Foo);
51 BOOST_TEST_TRAIT_SAME(axis::traits::value_type<axis::category<int>>, int);
52 BOOST_TEST_TRAIT_SAME(decltype(std::declval<axis::category<int>>().value(0)), int);
55 // empty axis::category
57 axis::category<int> a;
58 axis::category<int> b(std::vector<int>(0));
60 BOOST_TEST_EQ(a.size(), 0);
61 BOOST_TEST_EQ(a.index(-1), 0);
62 BOOST_TEST_EQ(a.index(0), 0);
63 BOOST_TEST_EQ(a.index(1), 0);
68 std::string A("A"), B("B"), C("C"), other;
70 axis::category<std::string> a({A, B, C}, "foo");
71 BOOST_TEST_EQ(a.metadata(), "foo");
72 BOOST_TEST_EQ(static_cast<const axis::category<std::string>&>(a).metadata(), "foo");
74 BOOST_TEST_EQ(static_cast<const axis::category<std::string>&>(a).metadata(), "bar");
75 BOOST_TEST_EQ(a.size(), 3);
76 BOOST_TEST_EQ(a.index(A), 0);
77 BOOST_TEST_EQ(a.index(B), 1);
78 BOOST_TEST_EQ(a.index(C), 2);
79 BOOST_TEST_EQ(a.index(other), 3);
80 BOOST_TEST_EQ(a.value(0), A);
81 BOOST_TEST_EQ(a.value(1), B);
82 BOOST_TEST_EQ(a.value(2), C);
83 BOOST_TEST_THROWS(a.value(3), std::out_of_range);
86 "category(\"A\", \"B\", \"C\", metadata=\"bar\", options=overflow)");
89 // category<int, axis::null_type>: copy, move
91 using C = axis::category<int, axis::null_type>;
111 // category<std::string>: copy, move
113 using C = axis::category<std::string>;
115 C a({"A", "B", "C"}, "foo");
117 BOOST_TEST_EQ(a2, a);
122 b = C{{"B", "A", "C"}};
134 // axis::category with growth
136 axis::category<int, axis::null_type, axis::option::growth_t> a;
137 BOOST_TEST_EQ(a.size(), 0);
138 BOOST_TEST_EQ(a.update(5), std::make_pair(0, -1));
139 BOOST_TEST_EQ(a.size(), 1);
140 BOOST_TEST_EQ(a.update(1), std::make_pair(1, -1));
141 BOOST_TEST_EQ(a.size(), 2);
142 BOOST_TEST_EQ(a.update(10), std::make_pair(2, -1));
143 BOOST_TEST_EQ(a.size(), 3);
144 BOOST_TEST_EQ(a.update(10), std::make_pair(2, 0));
145 BOOST_TEST_EQ(a.size(), 3);
147 BOOST_TEST_EQ(str(a), "category(5, 1, 10, options=growth)");
152 test_axis_iterator(axis::category<>({3, 1, 2}, ""), 0, 3);
153 test_axis_iterator(axis::category<std::string>({"A", "B"}, ""), 0, 2);
156 return boost::report_errors();