1 // (C) Copyright Thomas Witt 2003.
2 // (C) Copyright Hans Dembinski 2019.
3
4 // Distributed under the Boost Software License, Version 1.0. (See
5 // accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7
8 // See http://www.boost.org for most recent version including documentation.
9
10 #include <boost/core/lightweight_test.hpp>
11 #include <boost/core/lightweight_test_trait.hpp>
12 #include <boost/histogram/detail/iterator_adaptor.hpp>
13 #include <deque>
14 #include <set>
15 #include <type_traits>
16 #include <vector>
17 #include "std_ostream.hpp"
18 #include "utility_iterator.hpp"
19
20 using namespace boost::histogram;
21 using boost::histogram::detail::iterator_adaptor;
22
23 typedef std::deque<int> storage;
24 typedef std::deque<int*> pointer_deque;
25 typedef std::set<storage::iterator> iterator_set;
26
27 template <class T>
28 struct foo;
29
blah(int)30 void blah(int) {}
31
32 struct my_gen {
33 typedef int result_type;
my_genmy_gen34 my_gen() : n(0) {}
operator ()my_gen35 int operator()() { return ++n; }
36 int n;
37 };
38
39 template <class V>
40 struct ptr_iterator : iterator_adaptor<ptr_iterator<V>, V*> {
41 private:
42 typedef iterator_adaptor<ptr_iterator<V>, V*> super_t;
43
44 public:
45 using base_type = typename super_t::base_type;
46
ptr_iteratorptr_iterator47 ptr_iterator() {}
ptr_iteratorptr_iterator48 ptr_iterator(V* d) : super_t(d) {}
49
50 template <class V2, class = std::enable_if_t<std::is_convertible<V2*, V*>::value>>
ptr_iteratorptr_iterator51 ptr_iterator(const ptr_iterator<V2>& x) : super_t(x.base()) {}
52
operator *ptr_iterator53 V& operator*() const { return *(this->base()); }
54 };
55
56 template <class Iter>
57 struct constant_iterator
58 : iterator_adaptor<constant_iterator<Iter>, Iter,
59 typename std::iterator_traits<Iter>::value_type const&> {
60 typedef iterator_adaptor<constant_iterator<Iter>, Iter,
61 typename std::iterator_traits<Iter>::value_type const&>
62 base_t;
63
constant_iteratorconstant_iterator64 constant_iterator() {}
constant_iteratorconstant_iterator65 constant_iterator(Iter it) : base_t(it) {}
66
operator *constant_iterator67 typename std::iterator_traits<Iter>::value_type const& operator*() const {
68 this->base().operator*();
69 }
70 };
71
72 struct mutable_it : iterator_adaptor<mutable_it, int*> {
73 typedef iterator_adaptor<mutable_it, int*> super_t;
74
75 mutable_it();
mutable_itmutable_it76 explicit mutable_it(int* p) : super_t(p) {}
77
equalmutable_it78 bool equal(mutable_it const& rhs) const { return this->base() == rhs.base(); }
79 };
80
81 struct constant_it : iterator_adaptor<constant_it, int const*> {
82 typedef iterator_adaptor<constant_it, int const*> super_t;
83
84 constant_it();
constant_itconstant_it85 explicit constant_it(int* p) : super_t(p) {}
constant_itconstant_it86 constant_it(mutable_it const& x) : super_t(x.base()) {}
87
equalconstant_it88 bool equal(constant_it const& rhs) const { return this->base() == rhs.base(); }
89 };
90
91 template <class T>
92 class static_object {
93 public:
get()94 static T& get() {
95 static char d[sizeof(T)];
96 return *reinterpret_cast<T*>(d);
97 }
98 };
99
main()100 int main() {
101 dummyT array[] = {dummyT(0), dummyT(1), dummyT(2), dummyT(3), dummyT(4), dummyT(5)};
102 const int N = sizeof(array) / sizeof(dummyT);
103
104 // Test the iterator_adaptor
105 {
106 ptr_iterator<dummyT> i(array);
107 using reference = typename std::iterator_traits<ptr_iterator<dummyT>>::reference;
108 using pointer = typename std::iterator_traits<ptr_iterator<dummyT>>::pointer;
109 BOOST_TEST_TRAIT_SAME(reference, dummyT&);
110 BOOST_TEST_TRAIT_SAME(pointer, dummyT*);
111
112 random_access_iterator_test(i, N, array);
113
114 ptr_iterator<const dummyT> j(array);
115 random_access_iterator_test(j, N, array);
116 const_nonconst_iterator_test(i, ++j);
117 }
118
119 // Test the iterator_traits
120 {
121 // Test computation of defaults
122 typedef ptr_iterator<int> Iter1;
123 // don't use std::iterator_traits here to avoid VC++ problems
124 BOOST_TEST_TRAIT_SAME(Iter1::value_type, int);
125 BOOST_TEST_TRAIT_SAME(Iter1::reference, int&);
126 BOOST_TEST_TRAIT_SAME(Iter1::pointer, int*);
127 BOOST_TEST_TRAIT_SAME(Iter1::difference_type, std::ptrdiff_t);
128 }
129
130 {
131 // Test computation of default when the Value is const
132 typedef ptr_iterator<int const> Iter1;
133 BOOST_TEST_TRAIT_SAME(Iter1::value_type, int);
134 BOOST_TEST_TRAIT_SAME(Iter1::reference, const int&);
135 BOOST_TEST_TRAIT_SAME(Iter1::pointer, int const*);
136 }
137
138 {
139 // Test constant iterator idiom
140 typedef ptr_iterator<int> BaseIter;
141 typedef constant_iterator<BaseIter> Iter;
142
143 BOOST_TEST_TRAIT_SAME(Iter::value_type, int);
144 BOOST_TEST_TRAIT_SAME(Iter::reference, int const&);
145 BOOST_TEST_TRAIT_SAME(Iter::pointer, int const*);
146 }
147
148 // Test the iterator_adaptor
149 {
150 ptr_iterator<dummyT> i(array);
151 random_access_iterator_test(i, N, array);
152
153 ptr_iterator<const dummyT> j(array);
154 random_access_iterator_test(j, N, array);
155 const_nonconst_iterator_test(i, ++j);
156 }
157
158 // check that base_type is correct
159 {
160 // Test constant iterator idiom
161 typedef ptr_iterator<int> BaseIter;
162
163 BOOST_TEST_TRAIT_SAME(BaseIter::base_type, int*);
164 BOOST_TEST_TRAIT_SAME(constant_iterator<BaseIter>::base_type, BaseIter);
165 }
166
167 {
168 int data[] = {49, 77};
169
170 mutable_it i(data);
171 constant_it j(data + 1);
172 BOOST_TEST(i < j);
173 BOOST_TEST(j > i);
174 BOOST_TEST(i <= j);
175 BOOST_TEST(j >= i);
176 BOOST_TEST(j - i == 1);
177 BOOST_TEST(i - j == -1);
178
179 constant_it k = i;
180
181 BOOST_TEST(!(i < k));
182 BOOST_TEST(!(k > i));
183 BOOST_TEST(i <= k);
184 BOOST_TEST(k >= i);
185 BOOST_TEST(k - i == 0);
186 BOOST_TEST(i - k == 0);
187 }
188
189 return boost::report_errors();
190 }
191