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/sequence_container_interface.hpp>
7
8#include "ill_formed.hpp"
9
10#include <boost/core/lightweight_test.hpp>
11
12#include <array>
13#include <deque>
14#include <vector>
15
16
17// Just like std::array, except for the 0-size specialization, and the fact
18// that the base class makes brace-initialization wonky.
19template<typename T, std::size_t N>
20struct array : boost::stl_interfaces::sequence_container_interface<
21 array<T, N>,
22 boost::stl_interfaces::element_layout::contiguous>
23{
24 using value_type = T;
25 using pointer = T *;
26 using const_pointer = T const *;
27 using reference = value_type &;
28 using const_reference = value_type const &;
29 using size_type = std::size_t;
30 using difference_type = std::ptrdiff_t;
31 using iterator = T *;
32 using const_iterator = T const *;
33 using reverse_iterator = boost::stl_interfaces::reverse_iterator<iterator>;
34 using const_reverse_iterator =
35 boost::stl_interfaces::reverse_iterator<const_iterator>;
36
37 void fill(T const & x) { std::fill(begin(), end(), x); }
38
39 iterator begin() noexcept { return elements_; }
40 iterator end() noexcept { return elements_ + N; }
41
42 size_type max_size() const noexcept { return N; }
43
44 void swap(array & other)
45 {
46 using std::swap;
47 T * element = elements_;
48 for (auto & x : other) {
49 swap(*element++, x);
50 }
51 }
52
53 using base_type = boost::stl_interfaces::sequence_container_interface<
54 array<T, N>,
55 boost::stl_interfaces::element_layout::contiguous>;
56 using base_type::begin;
57 using base_type::end;
58
59 T elements_[N];
60};
61
62using arr_type = array<int, 5>;
63
64
65void test_comparisons()
66{
67 arr_type sm;
68 sm[0] = 1;
69 sm[1] = 2;
70 sm[2] = 3;
71 sm[3] = 0;
72 sm[4] = 0;
73 arr_type md;
74 md[0] = 1;
75 md[1] = 2;
76 md[2] = 3;
77 md[3] = 4;
78 md[4] = 0;
79 arr_type lg;
80 lg[0] = 1;
81 lg[1] = 2;
82 lg[2] = 3;
83 lg[3] = 4;
84 lg[4] = 5;
85
86 BOOST_TEST(sm == sm);
87 BOOST_TEST(!(sm == md));
88 BOOST_TEST(!(sm == lg));
89
90 BOOST_TEST(!(sm != sm));
91 BOOST_TEST(sm != md);
92 BOOST_TEST(sm != lg);
93
94 BOOST_TEST(!(sm < sm));
95 BOOST_TEST(sm < md);
96 BOOST_TEST(sm < lg);
97
98 BOOST_TEST(sm <= sm);
99 BOOST_TEST(sm <= md);
100 BOOST_TEST(sm <= lg);
101
102 BOOST_TEST(!(sm > sm));
103 BOOST_TEST(!(sm > md));
104 BOOST_TEST(!(sm > lg));
105
106 BOOST_TEST(sm >= sm);
107 BOOST_TEST(!(sm >= md));
108 BOOST_TEST(!(sm >= lg));
109
110
111 BOOST_TEST(!(md == sm));
112 BOOST_TEST(md == md);
113 BOOST_TEST(!(md == lg));
114
115 BOOST_TEST(!(md < sm));
116 BOOST_TEST(!(md < md));
117 BOOST_TEST(md < lg);
118
119 BOOST_TEST(!(md <= sm));
120 BOOST_TEST(md <= md);
121 BOOST_TEST(md <= lg);
122
123 BOOST_TEST(md > sm);
124 BOOST_TEST(!(md > md));
125 BOOST_TEST(!(md > lg));
126
127 BOOST_TEST(md >= sm);
128 BOOST_TEST(md >= md);
129 BOOST_TEST(!(md >= lg));
130
131
132 BOOST_TEST(!(lg == sm));
133 BOOST_TEST(!(lg == md));
134 BOOST_TEST(lg == lg);
135
136 BOOST_TEST(!(lg < sm));
137 BOOST_TEST(!(lg < md));
138 BOOST_TEST(!(lg < lg));
139
140 BOOST_TEST(!(lg <= sm));
141 BOOST_TEST(!(lg <= md));
142 BOOST_TEST(lg <= lg);
143
144 BOOST_TEST(lg > sm);
145 BOOST_TEST(lg > md);
146 BOOST_TEST(!(lg > lg));
147
148 BOOST_TEST(lg >= sm);
149 BOOST_TEST(lg >= md);
150 BOOST_TEST(lg >= lg);
151}
152
153
154void test_swap()
155{
156 {
157 arr_type v1;
158 v1[0] = 3;
159 v1[1] = 4;
160 v1[2] = 0;
161 v1[3] = 0;
162 v1[4] = 0;
163 arr_type v2;
164 v2[0] = 4;
165 v2[1] = 3;
166 v2[2] = 0;
167 v2[3] = 0;
168 v2[4] = 0;
169
170 arr_type const v1_copy = v1;
171 arr_type const v2_copy = v2;
172
173 static_assert(std::is_same<decltype(v1.swap(other&: v2)), void>::value, "");
174 static_assert(std::is_same<decltype(swap(lhs&: v1, rhs&: v2)), void>::value, "");
175
176 v1.swap(other&: v2);
177
178 BOOST_TEST(v1 == v2_copy);
179 BOOST_TEST(v2 == v1_copy);
180 }
181
182 {
183 arr_type v1;
184 v1[0] = 3;
185 v1[1] = 4;
186 v1[2] = 0;
187 v1[3] = 0;
188 v1[4] = 0;
189 arr_type v2;
190 v2[0] = 4;
191 v2[1] = 3;
192 v2[2] = 0;
193 v2[3] = 0;
194 v2[4] = 0;
195
196 arr_type const v1_copy = v1;
197 arr_type const v2_copy = v2;
198
199 swap(lhs&: v1, rhs&: v2);
200
201 BOOST_TEST(v1 == v2_copy);
202 BOOST_TEST(v2 == v1_copy);
203 }
204}
205
206template<typename Iter>
207using writable_iter_t = decltype(
208 *std::declval<Iter>() =
209 std::declval<typename std::iterator_traits<Iter>::value_type>());
210
211static_assert(
212 !ill_formed<writable_iter_t, decltype(std::declval<arr_type &>().begin())>::
213 value,
214 "");
215static_assert(
216 !ill_formed<writable_iter_t, decltype(std::declval<arr_type &>().end())>::
217 value,
218 "");
219
220static_assert(
221 ill_formed<
222 writable_iter_t,
223 decltype(std::declval<arr_type const &>().begin())>::value,
224 "");
225static_assert(
226 ill_formed<
227 writable_iter_t,
228 decltype(std::declval<arr_type const &>().end())>::value,
229 "");
230static_assert(
231 ill_formed<writable_iter_t, decltype(std::declval<arr_type &>().cbegin())>::
232 value,
233 "");
234static_assert(
235 ill_formed<writable_iter_t, decltype(std::declval<arr_type &>().cend())>::
236 value,
237 "");
238
239static_assert(
240 ill_formed<
241 writable_iter_t,
242 decltype(std::declval<arr_type const &>().rbegin())>::value,
243 "");
244static_assert(
245 ill_formed<
246 writable_iter_t,
247 decltype(std::declval<arr_type const &>().rend())>::value,
248 "");
249static_assert(
250 ill_formed<
251 writable_iter_t,
252 decltype(std::declval<arr_type &>().crbegin())>::value,
253 "");
254static_assert(
255 ill_formed<writable_iter_t, decltype(std::declval<arr_type &>().crend())>::
256 value,
257 "");
258
259void test_iterators()
260{
261 arr_type v0;
262 v0[0] = 3;
263 v0[1] = 2;
264 v0[2] = 1;
265 v0[3] = 0;
266 v0[4] = 0;
267
268 {
269 arr_type v = v0;
270
271 static_assert(
272 std::is_same<decltype(v.begin()), arr_type::iterator>::value, "");
273 static_assert(
274 std::is_same<decltype(v.end()), arr_type::iterator>::value, "");
275 static_assert(
276 std::is_same<decltype(v.cbegin()), arr_type::const_iterator>::value,
277 "");
278 static_assert(
279 std::is_same<decltype(v.cend()), arr_type::const_iterator>::value,
280 "");
281 static_assert(
282 std::is_same<decltype(v.rbegin()), arr_type::reverse_iterator>::
283 value,
284 "");
285 static_assert(
286 std::is_same<decltype(v.rbegin()), arr_type::reverse_iterator>::
287 value,
288 "");
289 static_assert(
290 std::is_same<
291 decltype(v.crbegin()),
292 arr_type::const_reverse_iterator>::value,
293 "");
294 static_assert(
295 std::is_same<
296 decltype(v.crbegin()),
297 arr_type::const_reverse_iterator>::value,
298 "");
299
300 std::array<int, 5> const a = {._M_elems: {3, 2, 1, 0, 0}};
301 std::array<int, 5> const ra = {._M_elems: {0, 0, 1, 2, 3}};
302
303 BOOST_TEST(std::equal(v.begin(), v.end(), a.begin(), a.end()));
304 BOOST_TEST(std::equal(v.cbegin(), v.cend(), a.begin(), a.end()));
305
306 BOOST_TEST(std::equal(v.rbegin(), v.rend(), ra.begin(), ra.end()));
307 BOOST_TEST(std::equal(v.crbegin(), v.crend(), ra.begin(), ra.end()));
308
309 arr_type v2;
310 v2[0] = 8;
311 v2[1] = 2;
312 v2[2] = 1;
313 v2[3] = 0;
314 v2[4] = 9;
315
316 *v.begin() = 8;
317 *v.rbegin() = 9;
318 BOOST_TEST(v == v2);
319 }
320
321 {
322 arr_type const v = v0;
323
324 static_assert(
325 std::is_same<decltype(v.begin()), arr_type::const_iterator>::value,
326 "");
327 static_assert(
328 std::is_same<decltype(v.end()), arr_type::const_iterator>::value,
329 "");
330 static_assert(
331 std::is_same<decltype(v.cbegin()), arr_type::const_iterator>::value,
332 "");
333 static_assert(
334 std::is_same<decltype(v.cend()), arr_type::const_iterator>::value,
335 "");
336 static_assert(
337 std::is_same<
338 decltype(v.rbegin()),
339 arr_type::const_reverse_iterator>::value,
340 "");
341 static_assert(
342 std::is_same<
343 decltype(v.rbegin()),
344 arr_type::const_reverse_iterator>::value,
345 "");
346 static_assert(
347 std::is_same<
348 decltype(v.crbegin()),
349 arr_type::const_reverse_iterator>::value,
350 "");
351 static_assert(
352 std::is_same<
353 decltype(v.crbegin()),
354 arr_type::const_reverse_iterator>::value,
355 "");
356
357 std::array<int, 5> const a = {._M_elems: {3, 2, 1, 0, 0}};
358 std::array<int, 5> const ra = {._M_elems: {0, 0, 1, 2, 3}};
359
360 BOOST_TEST(std::equal(v.begin(), v.end(), a.begin(), a.end()));
361 BOOST_TEST(std::equal(v.cbegin(), v.cend(), a.begin(), a.end()));
362
363 BOOST_TEST(std::equal(v.rbegin(), v.rend(), ra.begin(), ra.end()));
364 BOOST_TEST(std::equal(v.crbegin(), v.crend(), ra.begin(), ra.end()));
365 }
366}
367
368
369template<
370 typename Container,
371 typename ValueType = typename Container::value_type>
372using lvalue_push_front_t = decltype(
373 std::declval<Container &>().push_front(std::declval<ValueType const &>()));
374template<
375 typename Container,
376 typename ValueType = typename Container::value_type>
377using rvalue_push_front_t = decltype(std::declval<Container &>().push_front(0));
378template<typename Container>
379using pop_front_t = decltype(std::declval<Container &>().pop_front());
380
381static_assert(ill_formed<lvalue_push_front_t, arr_type>::value, "");
382static_assert(ill_formed<rvalue_push_front_t, arr_type>::value, "");
383static_assert(ill_formed<pop_front_t, arr_type>::value, "");
384
385using std_deq_int = std::deque<int>;
386
387static_assert(!ill_formed<lvalue_push_front_t, std_deq_int>::value, "");
388static_assert(!ill_formed<rvalue_push_front_t, std_deq_int>::value, "");
389static_assert(!ill_formed<pop_front_t, std_deq_int>::value, "");
390
391
392template<
393 typename Container,
394 typename ValueType = typename Container::value_type>
395using lvalue_push_back_t = decltype(
396 std::declval<Container &>().push_back(std::declval<ValueType const &>()));
397template<
398 typename Container,
399 typename ValueType = typename Container::value_type>
400using rvalue_push_back_t = decltype(std::declval<Container &>().push_back(0));
401template<typename Container>
402using pop_back_t = decltype(std::declval<Container &>().pop_back());
403
404static_assert(ill_formed<lvalue_push_back_t, arr_type>::value, "");
405static_assert(ill_formed<rvalue_push_back_t, arr_type>::value, "");
406static_assert(ill_formed<pop_back_t, arr_type>::value, "");
407
408using std_vec_int = std::vector<int>;
409
410static_assert(!ill_formed<lvalue_push_back_t, std_vec_int>::value, "");
411static_assert(!ill_formed<rvalue_push_back_t, std_vec_int>::value, "");
412static_assert(!ill_formed<pop_back_t, std_vec_int>::value, "");
413
414
415void test_front_back()
416{
417 {
418 arr_type v;
419 v[0] = 0;
420 v[1] = 0;
421 v[2] = 0;
422 v[3] = 0;
423 v[4] = 0;
424
425 static_assert(std::is_same<decltype(v.front()), int &>::value, "");
426 static_assert(std::is_same<decltype(v.back()), int &>::value, "");
427
428 v.front() = 9;
429 v.back() = 8;
430 BOOST_TEST(v[0] == v.front());
431 BOOST_TEST(v[4] == v.back());
432 }
433
434 {
435 arr_type v0;
436 v0[0] = 3;
437 v0[1] = 0;
438 v0[2] = 2;
439 v0[3] = 0;
440 v0[4] = 1;
441
442 arr_type const v = v0;
443 BOOST_TEST(v.front() == 3);
444 BOOST_TEST(v.back() == 1);
445
446 static_assert(
447 std::is_same<decltype(v.front()), int const &>::value, "");
448 static_assert(std::is_same<decltype(v.back()), int const &>::value, "");
449 }
450}
451
452
453void test_cindex_at()
454{
455 arr_type v0;
456 v0[0] = 3;
457 v0[1] = 2;
458 v0[2] = 1;
459 v0[3] = 0;
460 v0[4] = 0;
461
462 {
463 arr_type v = v0;
464 BOOST_TEST(v[0] == 3);
465 BOOST_TEST(v[1] == 2);
466 BOOST_TEST(v[2] == 1);
467 BOOST_TEST_NO_THROW(v.at(0));
468 BOOST_TEST_NO_THROW(v.at(1));
469 BOOST_TEST_NO_THROW(v.at(2));
470 BOOST_TEST_THROWS(v.at(5), std::out_of_range);
471
472 static_assert(std::is_same<decltype(v[0]), int &>::value, "");
473 static_assert(std::is_same<decltype(v.at(i: 0)), int &>::value, "");
474
475 v[0] = 8;
476 v.at(i: 1) = 9;
477 BOOST_TEST(v[0] == 8);
478 BOOST_TEST(v[1] == 9);
479 }
480
481 {
482 arr_type const v = v0;
483 BOOST_TEST(v[0] == 3);
484 BOOST_TEST(v[1] == 2);
485 BOOST_TEST(v[2] == 1);
486 BOOST_TEST_NO_THROW(v.at(0));
487 BOOST_TEST_NO_THROW(v.at(1));
488 BOOST_TEST_NO_THROW(v.at(2));
489 BOOST_TEST_THROWS(v.at(5), std::out_of_range);
490
491 static_assert(std::is_same<decltype(v[0]), int const &>::value, "");
492 static_assert(std::is_same<decltype(v.at(i: 0)), int const &>::value, "");
493 }
494}
495
496
497template<typename Container>
498using resize_t = decltype(std::declval<Container &>().resize(0));
499
500static_assert(ill_formed<resize_t, arr_type>::value, "");
501
502static_assert(!ill_formed<resize_t, std_vec_int>::value, "");
503
504template<
505 typename Container,
506 typename ValueType = typename Container::value_type>
507using lvalue_insert_t = decltype(std::declval<Container &>().insert(
508 std::declval<Container &>().begin(), std::declval<ValueType const &>()));
509template<
510 typename Container,
511 typename ValueType = typename Container::value_type>
512using rvalue_insert_t = decltype(std::declval<Container &>().insert(
513 std::declval<Container &>().begin(), std::declval<ValueType &&>()));
514template<
515 typename Container,
516 typename ValueType = typename Container::value_type>
517using insert_n_t = decltype(std::declval<Container &>().insert(
518 std::declval<Container &>().begin(), 2, std::declval<ValueType const &>()));
519template<
520 typename Container,
521 typename ValueType = typename Container::value_type>
522using insert_il_t = decltype(std::declval<Container &>().insert(
523 std::declval<Container &>().begin(), std::initializer_list<int>{}));
524
525static_assert(ill_formed<lvalue_insert_t, arr_type>::value, "");
526static_assert(ill_formed<rvalue_insert_t, arr_type>::value, "");
527
528#if BOOST_STL_INTERFACES_USE_CONCEPTS
529static_assert(ill_formed<insert_n_t, arr_type>::value, "");
530#endif
531
532static_assert(ill_formed<insert_il_t, arr_type>::value, "");
533
534static_assert(!ill_formed<lvalue_insert_t, std_vec_int>::value, "");
535static_assert(!ill_formed<rvalue_insert_t, std_vec_int>::value, "");
536static_assert(!ill_formed<insert_n_t, std_vec_int>::value, "");
537static_assert(!ill_formed<insert_il_t, std_vec_int>::value, "");
538
539
540template<typename Container>
541using erase_t = decltype(
542 std::declval<Container &>().erase(std::declval<Container &>().begin()));
543
544static_assert(ill_formed<erase_t, arr_type>::value, "");
545
546static_assert(!ill_formed<erase_t, std_vec_int>::value, "");
547
548
549template<typename Container>
550using assign_t = decltype(std::declval<Container &>().assign(
551 std::declval<int *>(), std::declval<int *>()));
552template<typename Container>
553using assign_n_t = decltype(std::declval<Container &>().assign(5, 5));
554template<typename Container>
555using assign_il_t =
556 decltype(std::declval<Container &>().assign(std::initializer_list<int>{}));
557template<typename Container>
558using assignment_operator_il_t =
559 decltype(std::declval<Container &>() = std::initializer_list<int>{});
560
561static_assert(ill_formed<assign_t, arr_type>::value, "");
562static_assert(ill_formed<assign_n_t, arr_type>::value, "");
563static_assert(ill_formed<assign_il_t, arr_type>::value, "");
564static_assert(ill_formed<assignment_operator_il_t, arr_type>::value, "");
565
566static_assert(!ill_formed<assign_t, std_vec_int>::value, "");
567static_assert(!ill_formed<assign_n_t, std_vec_int>::value, "");
568static_assert(!ill_formed<assign_il_t, std_vec_int>::value, "");
569static_assert(!ill_formed<assignment_operator_il_t, std_vec_int>::value, "");
570
571template<typename Container>
572using clear_t = decltype(std::declval<Container &>().clear());
573
574static_assert(ill_formed<clear_t, arr_type>::value, "");
575
576static_assert(!ill_formed<clear_t, std_vec_int>::value, "");
577
578int main()
579{
580 test_comparisons();
581 test_swap();
582 test_iterators();
583 test_front_back();
584 test_cindex_at();
585 return boost::report_errors();
586}
587

source code of boost/libs/stl_interfaces/test/array.cpp