• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2019 T. Zachary Laine
2 //
3 // Distributed under the Boost Software License, Version 1.0. (See
4 // accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6 #include <boost/stl_interfaces/iterator_interface.hpp>
7 
8 #include "ill_formed.hpp"
9 
10 #include <boost/core/lightweight_test.hpp>
11 
12 #include <algorithm>
13 #include <array>
14 #include <numeric>
15 #include <type_traits>
16 
17 
18 template<typename T>
19 using decrementable_t = decltype(--std::declval<T &>());
20 
21 struct basic_forward_iter
22     : boost::stl_interfaces::
23           iterator_interface<basic_forward_iter, std::forward_iterator_tag, int>
24 {
basic_forward_iterbasic_forward_iter25     basic_forward_iter() : it_(nullptr) {}
basic_forward_iterbasic_forward_iter26     basic_forward_iter(int * it) : it_(it) {}
27 
operator *basic_forward_iter28     int & operator*() const { return *it_; }
operator ++basic_forward_iter29     basic_forward_iter & operator++()
30     {
31         ++it_;
32         return *this;
33     }
34     friend bool
operator ==(basic_forward_iter lhs,basic_forward_iter rhs)35     operator==(basic_forward_iter lhs, basic_forward_iter rhs) noexcept
36     {
37         return lhs.it_ == rhs.it_;
38     }
39 
40     using base_type = boost::stl_interfaces::
41         iterator_interface<basic_forward_iter, std::forward_iterator_tag, int>;
42     using base_type::operator++;
43 
44 private:
45     int * it_;
46 };
47 
48 BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT(
49     basic_forward_iter, std::forward_iterator)
50 BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS(
51     basic_forward_iter,
52     std::forward_iterator_tag,
53     std::forward_iterator_tag,
54     int,
55     int &,
56     int *,
57     std::ptrdiff_t)
58 
59 static_assert(ill_formed<decrementable_t, basic_forward_iter>::value, "");
60 
61 template<typename ValueType>
62 struct forward_iter : boost::stl_interfaces::iterator_interface<
63                           forward_iter<ValueType>,
64                           std::forward_iterator_tag,
65                           ValueType>
66 {
forward_iterforward_iter67     forward_iter() : it_(nullptr) {}
forward_iterforward_iter68     forward_iter(ValueType * it) : it_(it) {}
69     template<
70         typename ValueType2,
71         typename E = std::enable_if_t<
72             std::is_convertible<ValueType2 *, ValueType *>::value>>
forward_iterforward_iter73     forward_iter(forward_iter<ValueType2> it) : it_(it.it_)
74     {}
75 
operator *forward_iter76     ValueType & operator*() const { return *it_; }
operator ++forward_iter77     forward_iter & operator++()
78     {
79         ++it_;
80         return *this;
81     }
operator ==(forward_iter lhs,forward_iter rhs)82     friend bool operator==(forward_iter lhs, forward_iter rhs) noexcept
83     {
84         return lhs.it_ == rhs.it_;
85     }
86 
87     using base_type = boost::stl_interfaces::iterator_interface<
88         forward_iter<ValueType>,
89         std::forward_iterator_tag,
90         ValueType>;
91     using base_type::operator++;
92 
93 private:
94     ValueType * it_;
95 
96     template<typename ValueType2>
97     friend struct forward_iter;
98 };
99 
100 using forward = forward_iter<int>;
101 using const_forward = forward_iter<int const>;
102 
103 static_assert(ill_formed<decrementable_t, forward>::value, "");
104 static_assert(ill_formed<decrementable_t, const_forward>::value, "");
105 
106 BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT(forward, std::forward_iterator)
107 BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS(
108     forward,
109     std::forward_iterator_tag,
110     std::forward_iterator_tag,
111     int,
112     int &,
113     int *,
114     std::ptrdiff_t)
115 
116 BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT(const_forward, std::forward_iterator)
117 BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS(
118     const_forward,
119     std::forward_iterator_tag,
120     std::forward_iterator_tag,
121     int,
122     int const &,
123     int const *,
124     std::ptrdiff_t)
125 
126 
127 std::array<int, 10> ints = {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}};
128 
129 
130 
131 ////////////////////
132 // view_interface //
133 ////////////////////
134 #include "view_tests.hpp"
135 
136 template<typename T>
137 using data_t = decltype(std::declval<T>().data());
138 
139 static_assert(
140     ill_formed<
141         data_t,
142         subrange<
143             basic_forward_iter,
144             basic_forward_iter,
145             boost::stl_interfaces::v1::element_layout::discontiguous>>::value,
146     "");
147 static_assert(
148     ill_formed<
149         data_t,
150         subrange<
151             basic_forward_iter,
152             basic_forward_iter,
153             boost::stl_interfaces::v1::element_layout::discontiguous> const>::
154         value,
155     "");
156 
157 template<typename T>
158 using size_t_ = decltype(std::declval<T>().size());
159 
160 static_assert(
161     ill_formed<
162         size_t_,
163         subrange<
164             basic_forward_iter,
165             basic_forward_iter,
166             boost::stl_interfaces::v1::element_layout::discontiguous>>::value,
167     "");
168 static_assert(
169     ill_formed<
170         size_t_,
171         subrange<
172             basic_forward_iter,
173             basic_forward_iter,
174             boost::stl_interfaces::v1::element_layout::discontiguous> const>::
175         value,
176     "");
177 
178 template<typename T>
179 using back_t_ = decltype(std::declval<T>().back());
180 
181 static_assert(
182     ill_formed<
183         back_t_,
184         subrange<
185             basic_forward_iter,
186             basic_forward_iter,
187             boost::stl_interfaces::v1::element_layout::discontiguous>>::value,
188     "");
189 static_assert(
190     ill_formed<
191         back_t_,
192         subrange<
193             basic_forward_iter,
194             basic_forward_iter,
195             boost::stl_interfaces::v1::element_layout::discontiguous> const>::
196         value,
197     "");
198 
199 template<typename T>
200 using index_operator_t = decltype(std::declval<T>()[0]);
201 
202 static_assert(
203     ill_formed<
204         index_operator_t,
205         subrange<
206             basic_forward_iter,
207             basic_forward_iter,
208             boost::stl_interfaces::v1::element_layout::discontiguous>>::value,
209     "");
210 static_assert(
211     ill_formed<
212         index_operator_t,
213         subrange<
214             basic_forward_iter,
215             basic_forward_iter,
216             boost::stl_interfaces::v1::element_layout::discontiguous> const>::
217         value,
218     "");
219 
220 
main()221 int main()
222 {
223 
224 {
225     basic_forward_iter first(ints.data());
226     basic_forward_iter last(ints.data() + ints.size());
227 
228     {
229         std::array<int, 10> ints_copy;
230         std::copy(first, last, ints_copy.begin());
231         BOOST_TEST(ints_copy == ints);
232     }
233 
234     {
235         std::array<int, 10> iota_ints;
236         basic_forward_iter first(iota_ints.data());
237         basic_forward_iter last(iota_ints.data() + iota_ints.size());
238         std::iota(first, last, 0);
239         BOOST_TEST(iota_ints == ints);
240     }
241 }
242 
243 
244 {
245     forward first(ints.data());
246     forward last(ints.data() + ints.size());
247     const_forward first_copy(first);
248     const_forward last_copy(last);
249     std::equal(first, last, first_copy, last_copy);
250 }
251 
252 
253 {
254     forward first(ints.data());
255     forward last(ints.data() + ints.size());
256     while (first != last)
257         first++;
258 }
259 
260 
261 {
262     forward first(ints.data());
263     forward last(ints.data() + ints.size());
264 
265     {
266         std::array<int, 10> ints_copy;
267         std::copy(first, last, ints_copy.begin());
268         BOOST_TEST(ints_copy == ints);
269     }
270 
271     {
272         std::array<int, 10> iota_ints;
273         forward first(iota_ints.data());
274         forward last(iota_ints.data() + iota_ints.size());
275         std::iota(first, last, 0);
276         BOOST_TEST(iota_ints == ints);
277     }
278 }
279 
280 
281 {
282     const_forward first(ints.data());
283     const_forward last(ints.data() + ints.size());
284 
285     {
286         std::array<int, 10> ints_copy;
287         std::copy(first, last, ints_copy.begin());
288         BOOST_TEST(ints_copy == ints);
289     }
290 
291     {
292         BOOST_TEST(std::binary_search(first, last, 3));
293     }
294 }
295 
296 {
297     basic_forward_iter first(ints.data());
298     basic_forward_iter last(ints.data() + ints.size());
299 
300     auto r = range<boost::stl_interfaces::v1::element_layout::discontiguous>(
301         first, last);
302     auto empty =
303         range<boost::stl_interfaces::v1::element_layout::discontiguous>(
304             first, first);
305 
306     // range begin/end
307     {
308         std::array<int, 10> ints_copy;
309         std::copy(r.begin(), r.end(), ints_copy.begin());
310         BOOST_TEST(ints_copy == ints);
311 
312         BOOST_TEST(empty.begin() == empty.end());
313     }
314 
315     // empty/op bool
316     {
317         BOOST_TEST(!r.empty());
318         BOOST_TEST(r);
319 
320         BOOST_TEST(empty.empty());
321         BOOST_TEST(!empty);
322 
323         auto const cr = r;
324         BOOST_TEST(!cr.empty());
325         BOOST_TEST(cr);
326 
327         auto const cempty = empty;
328         BOOST_TEST(cempty.empty());
329         BOOST_TEST(!cempty);
330     }
331 
332     // front/back
333     {
334         BOOST_TEST(r.front() == 0);
335 
336         auto const cr = r;
337         BOOST_TEST(cr.front() == 0);
338     }
339 }
340 
341     return boost::report_errors();
342 }
343