| // Copyright (C) 2019-2021 Free Software Foundation, Inc. |
| // |
| // This file is part of the GNU ISO C++ Library. This library is free |
| // software; you can redistribute it and/or modify it under the |
| // terms of the GNU General Public License as published by the |
| // Free Software Foundation; either version 3, or (at your option) |
| // any later version. |
| |
| // This library is distributed in the hope that it will be useful, |
| // but WITHOUT ANY WARRANTY; without even the implied warranty of |
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| // GNU General Public License for more details. |
| |
| // You should have received a copy of the GNU General Public License along |
| // with this library; see the file COPYING3. If not see |
| // <http://www.gnu.org/licenses/>. |
| |
| // { dg-options "-std=gnu++2a" } |
| // { dg-do run { target c++2a } } |
| |
| #include <iterator> |
| #include <testsuite_hooks.h> |
| |
| void |
| test01() |
| { |
| using I = std::common_iterator<int*, const int*>; |
| static_assert( std::is_default_constructible_v<I> ); |
| static_assert( std::is_copy_constructible_v<I> ); |
| static_assert( std::is_copy_assignable_v<I> ); |
| static_assert( std::is_constructible_v<I, int*> ); |
| static_assert( std::is_constructible_v<I, const int*> ); |
| |
| struct sentinel { operator int*() const { return nullptr; } }; |
| using K = std::common_iterator<int*, sentinel>; |
| static_assert( std::is_constructible_v<I, const K&> ); |
| static_assert( std::is_assignable_v<I, const K&> ); |
| |
| struct sentinel2 |
| { |
| const int* p; |
| sentinel2(const int* p = 0) : p(p) { } |
| bool operator==(const int* p) const { return p == this->p; } |
| }; |
| |
| using J = std::common_iterator<const int*, sentinel2>; |
| static_assert( std::is_constructible_v<J, const I&> ); |
| static_assert( std::is_convertible_v<const I&, J> ); |
| } |
| |
| void |
| test02() |
| { |
| struct sentinel { int limit; }; |
| |
| struct iterator |
| { |
| using iterator_category = std::input_iterator_tag; |
| using value_type = int; |
| using difference_type = std::ptrdiff_t; |
| using reference = const int&; |
| |
| const int& operator*() const { return counter; } |
| |
| iterator& operator++() { ++counter; return *this; } |
| |
| iterator operator++(int) { auto i = *this; ++counter; return i; } |
| |
| bool operator==(sentinel s) const { return counter == s.limit; } |
| |
| int counter = 0; |
| }; |
| |
| static_assert( std::sentinel_for<sentinel, iterator> ); |
| |
| int out[5] = { }; |
| std::common_iterator<int*, const int*> obegin = std::begin(out); |
| std::common_iterator<int*, const int*> oend = std::cend(out); |
| |
| iterator i; |
| sentinel s{5}; |
| std::common_iterator<iterator, sentinel> begin = i, end = s; |
| while (begin != end) |
| *obegin++ = *begin++; |
| |
| VERIFY(obegin == oend); |
| for (int& i : out) |
| VERIFY( i == (&i - out) ); |
| } |
| |
| void |
| test03() |
| { |
| int arr[2] = { 1, 2 }; |
| std::common_iterator<int*, const int*> i = std::ranges::begin(arr); |
| std::common_iterator<int*, const int*> end = std::ranges::cend(arr); |
| VERIFY( i != end ); |
| VERIFY( (end - i) == 2 ); |
| VERIFY( (i - end) == -2 ); |
| auto j = i; |
| VERIFY( j == i ); |
| VERIFY( (j - i) == 0 ); |
| j = end; |
| VERIFY( j != i ); |
| VERIFY( j == end ); |
| j = std::ranges::next(i); |
| VERIFY( j != i ); |
| VERIFY( j != end ); |
| VERIFY( (end - j) == 1 ); |
| VERIFY( (j - i) == 1 ); |
| VERIFY( (i - j) == -1 ); |
| ++j; |
| VERIFY( j == end ); |
| VERIFY( (end - j) == 0 ); |
| j = i; |
| VERIFY( j == i ); |
| VERIFY( (j - end) == -2 ); |
| VERIFY( (j - i) == 0 ); |
| |
| try |
| { |
| struct S { operator const int*() const { throw 1; } }; |
| i = std::common_iterator<int*, S>(S{}); |
| VERIFY( false ); |
| } |
| catch (int) |
| { |
| } |
| } |
| |
| void |
| test04() |
| { |
| struct X |
| { |
| X(int i) : i(i) { } |
| X(X&& x) : i(x.i) { x.i = -1; } |
| X& operator=(X&& x) { i = x.i; x.i = 0; return *this; } |
| int i; |
| }; |
| |
| X arr[] = { 1, 2 }; |
| std::common_iterator<X*, const X*> i(arr), j(arr+1); |
| std::ranges::iter_swap(i, j); |
| VERIFY( arr[0].i == 2 ); |
| VERIFY( arr[1].i == 1 ); |
| |
| X x = std::ranges::iter_move(i); |
| VERIFY( arr[0].i == -1 ); |
| VERIFY( x.i == 2 ); |
| } |
| |
| int |
| main() |
| { |
| test01(); |
| test02(); |
| test03(); |
| test04(); |
| } |