Commit 6d0dff49 by Jonathan Wakely Committed by Jonathan Wakely

Add iterator concepts and range access customization points for C++20

This adds most of the new C++20 features to <iterator>, as well as a few
initial pieces of <ranges> (but no actual <ranges> header just yet).

	* include/Makefile.am: Add new header.
	* include/Makefile.in: Regenerate.
	* include/bits/iterator_concepts.h: New header.
	(contiguous_iterator_tag, iter_reference_t, ranges::iter_move)
	(iter_rvalue_reference_t, incrementable_traits, iter_difference_t)
	(readable_traits, iter_value_t, readable, iter_common_reference_t)
	(writable, waekly_incrementable, incrementable)
	(input_or_output_iterator, sentinel_for, disable_sized_sentinel)
	(sized_sentinel_for, input_iterator, output_iterator)
	(forward_iterator, bidirectional_iterator, random_access_iterator)
	(contiguous_iterator, indirectly_unary_invocable)
	(indirectly_regular_unary_invocable, indirect_unary_predicate)
	(indirect_relation, indirect_strict_weak_order, indirect_result_t)
	(projected, indirectly_movable, indirectly_movable_storable)
	(indirectly_copyable, indirectly_copyable_storable, ranges::iter_swap)
	(indirectly_swappable, indirectly_comparable, permutable, mergeable)
	(sortable, unreachable_sentinel_t, unreachable_sentinel)
	(default_sentinel_t, default_sentinel): Define.
	(__detail::__cpp17_iterator, __detail::__cpp17_input_iterator)
	(__detail::__cpp17_fwd_iterator, __detail::__cpp17_bidi_iterator)
	(__detail::__cpp17_randacc_iterator): Define.
	(__iterator_traits): Define constrained specializations.
	* include/bits/move.h (move): Only use old concept check for C++98.
	* include/bits/range_access.h (ranges::disable_sized_range)
	(ranges::begin, ranges::end, ranges::cbegin, ranges::cend)
	(ranges::rbegin, ranges::rend, ranges::crbegin, ranges::crend)
	(ranges::size, ranges::empty, ranges::data, ranges::cdata): Define
	new customization points for C++20.
	(ranges::range, ranges::sized_range): Define new concepts for C++20.
	(ranges::advance, ranges::distance, ranges::next, ranges::prev):
	Define new functions for C++20.
	(__adl_end, __adl_cdata, __adl_cbegin, __adl_cend, __adl_rbegin)
	(__adl_rend, __adl_crbegin, __adl_crend, __adl_cdata, __adl_size)
	(__adl_empty): Remove.
	* include/bits/stl_iterator.h (disable_sized_sentinel): Specialize
	for reverse_iterator.
	* include/bits/stl_iterator_base_types.h (contiguous_iterator_tag):
	Define new struct for C++20.
	(iterator_traits<_Tp*>): Constrain partial specialization in C++20.
	* include/std/concepts (__is_class_or_enum): Move to __detail
	namespace.
	* testsuite/20_util/forward/c_neg.cc: Adjust dg-error line number.
	* testsuite/20_util/forward/f_neg.cc: Likewise.
	* testsuite/24_iterators/associated_types/incrementable.traits.cc: New
	test.
	* testsuite/24_iterators/associated_types/readable.traits.cc: New test.
	* testsuite/24_iterators/contiguous/concept.cc: New test.
	* testsuite/24_iterators/contiguous/tag.cc: New test.
	* testsuite/24_iterators/customization_points/iter_move.cc: New test.
	* testsuite/24_iterators/customization_points/iter_swap.cc: New test.
	* testsuite/24_iterators/headers/iterator/synopsis_c++20.cc: New test.
	* testsuite/24_iterators/range_operations/advance.cc: New test.
	* testsuite/24_iterators/range_operations/distance.cc: New test.
	* testsuite/24_iterators/range_operations/next.cc: New test.
	* testsuite/24_iterators/range_operations/prev.cc: New test.
	* testsuite/26_numerics/adjacent_difference/requirements/
	explicit_instantiation/2.cc: Rename types that conflict with C++20
	concepts.
	* testsuite/26_numerics/adjacent_difference/requirements/
	explicit_instantiation/pod.cc: Likewise.
	* testsuite/26_numerics/partial_sum/requirements/
	explicit_instantiation/2.cc: Likewise.
	* testsuite/26_numerics/partial_sum/requirements/
	explicit_instantiation/pod.cc: Likewise.
	* testsuite/experimental/iterator/requirements.cc: Likewise.
	* testsuite/std/ranges/access/begin.cc: New test.
	* testsuite/std/ranges/access/cbegin.cc: New test.
	* testsuite/std/ranges/access/cdata.cc: New test.
	* testsuite/std/ranges/access/cend.cc: New test.
	* testsuite/std/ranges/access/crbegin.cc: New test.
	* testsuite/std/ranges/access/crend.cc: New test.
	* testsuite/std/ranges/access/data.cc: New test.
	* testsuite/std/ranges/access/empty.cc: New test.
	* testsuite/std/ranges/access/end.cc: New test.
	* testsuite/std/ranges/access/rbegin.cc: New test.
	* testsuite/std/ranges/access/rend.cc: New test.
	* testsuite/std/ranges/access/size.cc: New test.
	* testsuite/util/testsuite_iterators.h (contiguous_iterator_wrapper)
	(test_range, test_sized_range): New test utilities.

From-SVN: r277579
parent 9921ac3d
2019-10-29 Jonathan Wakely <jwakely@redhat.com>
* include/Makefile.am: Add new header.
* include/Makefile.in: Regenerate.
* include/bits/iterator_concepts.h: New header.
(contiguous_iterator_tag, iter_reference_t, ranges::iter_move)
(iter_rvalue_reference_t, incrementable_traits, iter_difference_t)
(readable_traits, iter_value_t, readable, iter_common_reference_t)
(writable, waekly_incrementable, incrementable)
(input_or_output_iterator, sentinel_for, disable_sized_sentinel)
(sized_sentinel_for, input_iterator, output_iterator)
(forward_iterator, bidirectional_iterator, random_access_iterator)
(contiguous_iterator, indirectly_unary_invocable)
(indirectly_regular_unary_invocable, indirect_unary_predicate)
(indirect_relation, indirect_strict_weak_order, indirect_result_t)
(projected, indirectly_movable, indirectly_movable_storable)
(indirectly_copyable, indirectly_copyable_storable, ranges::iter_swap)
(indirectly_swappable, indirectly_comparable, permutable, mergeable)
(sortable, unreachable_sentinel_t, unreachable_sentinel)
(default_sentinel_t, default_sentinel): Define.
(__detail::__cpp17_iterator, __detail::__cpp17_input_iterator)
(__detail::__cpp17_fwd_iterator, __detail::__cpp17_bidi_iterator)
(__detail::__cpp17_randacc_iterator): Define.
(__iterator_traits): Define constrained specializations.
* include/bits/move.h (move): Only use old concept check for C++98.
* include/bits/range_access.h (ranges::disable_sized_range)
(ranges::begin, ranges::end, ranges::cbegin, ranges::cend)
(ranges::rbegin, ranges::rend, ranges::crbegin, ranges::crend)
(ranges::size, ranges::empty, ranges::data, ranges::cdata): Define
new customization points for C++20.
(ranges::range, ranges::sized_range): Define new concepts for C++20.
(ranges::advance, ranges::distance, ranges::next, ranges::prev):
Define new functions for C++20.
(__adl_end, __adl_cdata, __adl_cbegin, __adl_cend, __adl_rbegin)
(__adl_rend, __adl_crbegin, __adl_crend, __adl_cdata, __adl_size)
(__adl_empty): Remove.
* include/bits/stl_iterator.h (disable_sized_sentinel): Specialize
for reverse_iterator.
* include/bits/stl_iterator_base_types.h (contiguous_iterator_tag):
Define new struct for C++20.
(iterator_traits<_Tp*>): Constrain partial specialization in C++20.
* include/std/concepts (__is_class_or_enum): Move to __detail
namespace.
* testsuite/20_util/forward/c_neg.cc: Adjust dg-error line number.
* testsuite/20_util/forward/f_neg.cc: Likewise.
* testsuite/24_iterators/associated_types/incrementable.traits.cc: New
test.
* testsuite/24_iterators/associated_types/readable.traits.cc: New test.
* testsuite/24_iterators/contiguous/concept.cc: New test.
* testsuite/24_iterators/contiguous/tag.cc: New test.
* testsuite/24_iterators/customization_points/iter_move.cc: New test.
* testsuite/24_iterators/customization_points/iter_swap.cc: New test.
* testsuite/24_iterators/headers/iterator/synopsis_c++20.cc: New test.
* testsuite/24_iterators/range_operations/advance.cc: New test.
* testsuite/24_iterators/range_operations/distance.cc: New test.
* testsuite/24_iterators/range_operations/next.cc: New test.
* testsuite/24_iterators/range_operations/prev.cc: New test.
* testsuite/26_numerics/adjacent_difference/requirements/
explicit_instantiation/2.cc: Rename types that conflict with C++20
concepts.
* testsuite/26_numerics/adjacent_difference/requirements/
explicit_instantiation/pod.cc: Likewise.
* testsuite/26_numerics/partial_sum/requirements/
explicit_instantiation/2.cc: Likewise.
* testsuite/26_numerics/partial_sum/requirements/
explicit_instantiation/pod.cc: Likewise.
* testsuite/experimental/iterator/requirements.cc: Likewise.
* testsuite/std/ranges/access/begin.cc: New test.
* testsuite/std/ranges/access/cbegin.cc: New test.
* testsuite/std/ranges/access/cdata.cc: New test.
* testsuite/std/ranges/access/cend.cc: New test.
* testsuite/std/ranges/access/crbegin.cc: New test.
* testsuite/std/ranges/access/crend.cc: New test.
* testsuite/std/ranges/access/data.cc: New test.
* testsuite/std/ranges/access/empty.cc: New test.
* testsuite/std/ranges/access/end.cc: New test.
* testsuite/std/ranges/access/rbegin.cc: New test.
* testsuite/std/ranges/access/rend.cc: New test.
* testsuite/std/ranges/access/size.cc: New test.
* testsuite/util/testsuite_iterators.h (contiguous_iterator_wrapper)
(test_range, test_sized_range): New test utilities.
* testsuite/util/testsuite_iterators.h (BoundsContainer::size()): Add
new member function.
(WritableObject::operator=): Constrain with enable_if when available.
......
......@@ -129,6 +129,7 @@ bits_headers = \
${bits_srcdir}/invoke.h \
${bits_srcdir}/ios_base.h \
${bits_srcdir}/istream.tcc \
${bits_srcdir}/iterator_concepts.h \
${bits_srcdir}/list.tcc \
${bits_srcdir}/locale_classes.h \
${bits_srcdir}/locale_classes.tcc \
......
......@@ -473,6 +473,7 @@ bits_headers = \
${bits_srcdir}/invoke.h \
${bits_srcdir}/ios_base.h \
${bits_srcdir}/istream.tcc \
${bits_srcdir}/iterator_concepts.h \
${bits_srcdir}/list.tcc \
${bits_srcdir}/locale_classes.h \
${bits_srcdir}/locale_classes.tcc \
......
......@@ -31,7 +31,9 @@
#define _MOVE_H 1
#include <bits/c++config.h>
#include <bits/concept_check.h>
#if __cplusplus < 201103L
# include <bits/concept_check.h>
#endif
namespace std _GLIBCXX_VISIBILITY(default)
{
......@@ -188,9 +190,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_NOEXCEPT_IF(__and_<is_nothrow_move_constructible<_Tp>,
is_nothrow_move_assignable<_Tp>>::value)
{
#if __cplusplus < 201103L
// concept requirements
__glibcxx_function_requires(_SGIAssignableConcept<_Tp>)
#endif
_Tp __tmp = _GLIBCXX_MOVE(__a);
__a = _GLIBCXX_MOVE(__b);
__b = _GLIBCXX_MOVE(__tmp);
......
......@@ -431,7 +431,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__make_reverse_iterator(_Iterator __i)
{ return reverse_iterator<_Iterator>(__i); }
# if __cplusplus > 201103L
# if __cplusplus >= 201402L
# define __cpp_lib_make_reverse_iterator 201402
// _GLIBCXX_RESOLVE_LIB_DEFECTS
......@@ -441,10 +441,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
inline _GLIBCXX17_CONSTEXPR reverse_iterator<_Iterator>
make_reverse_iterator(_Iterator __i)
{ return reverse_iterator<_Iterator>(__i); }
# endif
#endif
#if __cplusplus >= 201103L
# if __cplusplus > 201703L
template<typename _Iterator1, typename _Iterator2>
requires (!sized_sentinel_for<_Iterator1, _Iterator2>)
inline constexpr bool disable_sized_sentinel<reverse_iterator<_Iterator1>,
reverse_iterator<_Iterator2>>
= true;
# endif // C++20
# endif // C++14
template<typename _Iterator>
_GLIBCXX20_CONSTEXPR
auto
......@@ -463,7 +469,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__miter_base(reverse_iterator<_Iterator> __it)
-> decltype(__make_reverse_iterator(__miter_base(__it.base())))
{ return __make_reverse_iterator(__miter_base(__it.base())); }
#endif
#endif // C++11
// 24.4.2.2.1 back_insert_iterator
/**
......
......@@ -67,6 +67,10 @@
# include <type_traits> // For __void_t, is_convertible
#endif
#if __cplusplus > 201703L && __cpp_concepts
# include <bits/iterator_concepts.h>
#endif
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
......@@ -101,6 +105,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// Random-access iterators support a superset of bidirectional
/// iterator operations.
struct random_access_iterator_tag : public bidirectional_iterator_tag { };
#if __cplusplus > 201703L
/// Contiguous iterators point to objects stored contiguously in memory.
struct contiguous_iterator_tag : public random_access_iterator_tag { };
#endif
//@}
/**
......@@ -137,12 +146,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* argument. Specialized versions for pointers and pointers-to-const
* provide tighter, more correct semantics.
*/
template<typename _Iterator>
struct iterator_traits;
#if __cplusplus >= 201103L
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 2408. SFINAE-friendly common_type/iterator_traits is missing in C++14
template<typename _Iterator, typename = __void_t<>>
struct __iterator_traits { };
#if ! __cpp_lib_concepts
template<typename _Iterator>
struct __iterator_traits<_Iterator,
__void_t<typename _Iterator::iterator_category,
......@@ -157,11 +171,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typedef typename _Iterator::pointer pointer;
typedef typename _Iterator::reference reference;
};
#endif // ! concepts
template<typename _Iterator>
struct iterator_traits
: public __iterator_traits<_Iterator> { };
#else
#else // ! C++11
template<typename _Iterator>
struct iterator_traits
{
......@@ -171,8 +187,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typedef typename _Iterator::pointer pointer;
typedef typename _Iterator::reference reference;
};
#endif
#endif // C++11
#if __cplusplus > 201703L
/// Partial specialization for object pointer types.
template<typename _Tp>
#if __cpp_concepts
requires is_object_v<_Tp>
#endif
struct iterator_traits<_Tp*>
{
using iterator_concept = contiguous_iterator_tag;
using iterator_category = random_access_iterator_tag;
using value_type = remove_cv_t<_Tp>;
using difference_type = ptrdiff_t;
using pointer = _Tp*;
using reference = _Tp&;
};
#else
/// Partial specialization for pointer types.
template<typename _Tp>
struct iterator_traits<_Tp*>
......@@ -194,6 +226,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typedef const _Tp* pointer;
typedef const _Tp& reference;
};
#endif
/**
* This function is not a part of the C++ standard but is syntactic
......
......@@ -114,6 +114,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
template<typename _Tp>
using __cref = const remove_reference_t<_Tp>&;
template<typename _Tp>
concept __class_or_enum
= is_class_v<_Tp> || is_union_v<_Tp> || is_enum_v<_Tp>;
} // namespace __detail
/// [concept.assignable], concept assignable_from
......@@ -159,14 +163,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
template<typename _Tp> void swap(_Tp&, _Tp&) = delete;
template<typename _Tp>
concept __class_or_enum
= is_class_v<_Tp> || is_union_v<_Tp> || is_enum_v<_Tp>;
template<typename _Tp, typename _Up>
concept __adl_swap
= (__class_or_enum<remove_cvref_t<_Tp>>
|| __class_or_enum<remove_cvref_t<_Up>>)
= (__detail::__class_or_enum<remove_reference_t<_Tp>>
|| __detail::__class_or_enum<remove_reference_t<_Up>>)
&& requires(_Tp&& __t, _Up&& __u) {
swap(static_cast<_Tp&&>(__t), static_cast<_Up&&>(__u));
};
......@@ -175,7 +175,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
template<typename _Tp, typename _Up>
requires __adl_swap<_Tp, _Up>
constexpr void operator()(_Tp&& __t, _Up&& __u) const
constexpr void
operator()(_Tp&& __t, _Up&& __u) const
noexcept(noexcept(swap(std::declval<_Tp>(), std::declval<_Up>())))
{ swap(static_cast<_Tp&&>(__t), static_cast<_Up&&>(__u)); }
......
......@@ -17,7 +17,7 @@
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
// { dg-error "static assertion failed" "" { target *-*-* } 87 }
// { dg-error "static assertion failed" "" { target *-*-* } 89 }
#include <list>
......
......@@ -17,7 +17,7 @@
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
// { dg-error "static assertion failed" "" { target *-*-* } 87 }
// { dg-error "static assertion failed" "" { target *-*-* } 89 }
#include <utility>
......
// Copyright (C) 2019 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 compile { target c++2a } }
#include <iterator>
struct none;
template<typename T>
concept has_inc_traits_type
= requires { typename std::incrementable_traits<T>::difference_type; };
// Check std::incrementable_traits<T>::difference_type is U (or doesn't exist).
template<typename T, typename U>
concept check_inc_traits = (has_inc_traits_type<T> != std::same_as<U, none>);
static_assert( check_inc_traits<void, none> );
static_assert( check_inc_traits<const void, none> );
static_assert( check_inc_traits<void*, none> );
static_assert( check_inc_traits<const void*, none> );
static_assert( check_inc_traits<int, int> );
static_assert( check_inc_traits<const int, int> );
static_assert( check_inc_traits<int*, std::ptrdiff_t> );
static_assert( check_inc_traits<const int*, std::ptrdiff_t> );
static_assert( check_inc_traits<int[2], std::ptrdiff_t> );
static_assert( check_inc_traits<const int[2], std::ptrdiff_t> );
struct A { using difference_type = int; };
static_assert( check_inc_traits<A, int> );
static_assert( check_inc_traits<const A, int> );
struct B : private A { };
static_assert( check_inc_traits<B, none> );
struct C { };
short operator-(C, C) { return 0; }
static_assert( check_inc_traits<C, short> );
static_assert( check_inc_traits<const C, short> );
struct D { };
unsigned short operator-(D, D) { return 0; }
static_assert( check_inc_traits<D, short> );
static_assert( check_inc_traits<const D, short> );
struct E { };
template<>
struct std::incrementable_traits<E> { using difference_type = long; };
static_assert( check_inc_traits<E, long> );
static_assert( check_inc_traits<const E, long> );
template<typename T>
concept has_alias = requires { typename std::iter_difference_t<T>; };
// Check std::iter_difference_t<T> is U (or doesn't exist).
template<typename T, typename U>
concept check_alias = (has_alias<T> != std::same_as<U, none>);
static_assert( check_alias<void, none> );
static_assert( check_alias<const void, none> );
static_assert( check_alias<void*, none> );
static_assert( check_alias<const void*, none> );
static_assert( check_alias<int, int> );
static_assert( check_alias<const int, int> );
static_assert( check_alias<int*, std::ptrdiff_t> );
static_assert( check_alias<const int*, std::ptrdiff_t> );
static_assert( check_alias<int[2], std::ptrdiff_t> );
static_assert( check_alias<const int[2], std::ptrdiff_t> );
static_assert( check_alias<A, int> );
static_assert( check_alias<const A, int> );
static_assert( check_alias<B, none> );
static_assert( check_alias<C, short> );
static_assert( check_alias<const C, short> );
static_assert( check_alias<D, short> );
static_assert( check_alias<const D, short> );
static_assert( check_alias<E, long> );
static_assert( check_alias<const E, long> );
struct F { };
template<>
struct std::iterator_traits<F> { using difference_type = F; };
// iterator_traits<F> is specialized, so use its difference_type.
static_assert( check_alias<F, std::iterator_traits<F>::difference_type> );
struct G { };
template<>
struct std::incrementable_traits<G> { using difference_type = G; };
template<>
struct std::iterator_traits<G> { using difference_type = int; };
// iterator_traits<G> is specialized, so use its difference_type.
static_assert( check_alias<G, std::iterator_traits<G>::difference_type> );
struct H { };
template<>
struct std::incrementable_traits<H> { using difference_type = H; };
template<>
struct std::iterator_traits<H>
{
using iterator_category = input_iterator_tag;
using difference_type = int;
using value_type = char;
using reference = value_type&;
};
// iterator_traits<H> is specialized, so use its difference_type.
static_assert( check_alias<H, std::iterator_traits<H>::difference_type> );
struct I
{
using difference_type = I;
};
// iterator_traits<I> is not specialized, and no standard specialization
// matches, so use incrementable_traits.
static_assert( check_alias<I, std::incrementable_traits<I>::difference_type> );
struct J
{
using iterator_category = std::input_iterator_tag;
using difference_type = int;
using value_type = char;
using reference = value_type&;
};
// iterator_traits<J> matches constrained specialization in the library,
// so use its difference_type.
static_assert( check_alias<J, int> );
// Copyright (C) 2019 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 compile { target c++2a } }
#include <iterator>
struct none;
template<typename T>
concept has_readable_traits_type
= requires { typename std::readable_traits<T>::value_type; };
// Check std::readable_traits<T>::value_type is U (or doesn't exist).
template<typename T, typename U>
concept check_readable_traits
= (has_readable_traits_type<T> != std::same_as<U, none>);
static_assert( check_readable_traits<void, none> );
static_assert( check_readable_traits<const void, none> );
static_assert( check_readable_traits<void*, none> );
static_assert( check_readable_traits<const void*, none> );
static_assert( check_readable_traits<int, none> );
static_assert( check_readable_traits<const int, none> );
static_assert( check_readable_traits<int*, int> );
static_assert( check_readable_traits<const int*, int> );
static_assert( check_readable_traits<int[2], int> );
static_assert( check_readable_traits<const int[2], int> );
struct A { using value_type = int; };
static_assert( check_readable_traits<A, int> );
static_assert( check_readable_traits<const A, int> );
struct B : private A { };
static_assert( check_readable_traits<B, none> );
struct C { };
short operator-(C, C) { return 0; }
static_assert( check_readable_traits<C, none> );
static_assert( check_readable_traits<const C, none> );
struct D { long operator*() const { return 1L; } };
unsigned short operator-(D, D) { return 0; }
static_assert( check_readable_traits<D, none> );
static_assert( check_readable_traits<const D, none> );
struct E { };
template<>
struct std::readable_traits<E> { using value_type = long; };
static_assert( check_readable_traits<E, long> );
static_assert( check_readable_traits<const E, long> );
template<typename T>
concept has_alias = requires { typename std::iter_value_t<T>; };
// Check std::iter_value_t<T> is U (or doesn't exist).
template<typename T, typename U>
concept check_alias = (has_alias<T> != std::same_as<U, none>);
static_assert( check_alias<void, none> );
static_assert( check_alias<const void, none> );
static_assert( check_alias<void*, none> );
static_assert( check_alias<const void*, none> );
static_assert( check_alias<int, none> );
static_assert( check_alias<const int, none> );
static_assert( check_alias<int*, std::ptrdiff_t> );
static_assert( check_alias<const int*, std::ptrdiff_t> );
static_assert( check_alias<int[2], std::ptrdiff_t> );
static_assert( check_alias<const int[2], std::ptrdiff_t> );
static_assert( check_alias<A, int> );
static_assert( check_alias<const A, int> );
static_assert( check_alias<B, none> );
static_assert( check_alias<C, none> );
static_assert( check_alias<const C, none> );
static_assert( check_alias<D, none> );
static_assert( check_alias<const D, none> );
static_assert( check_alias<E, long> );
static_assert( check_alias<const E, long> );
struct F { };
template<>
struct std::iterator_traits<F> { using value_type = F; };
// iterator_traits<F> is specialized, so use its value_type.
static_assert( check_alias<F, std::iterator_traits<F>::value_type> );
struct G { };
template<>
struct std::readable_traits<G> { using value_type = G; };
template<>
struct std::iterator_traits<G> { using value_type = int; };
// iterator_traits<G> is specialized, so use its value_type.
static_assert( check_alias<G, std::iterator_traits<G>::value_type> );
struct H { };
template<>
struct std::readable_traits<H> { using value_type = H; };
template<>
struct std::iterator_traits<H>
{
using iterator_category = input_iterator_tag;
using difference_type = int;
using value_type = char;
using reference = value_type&;
};
// iterator_traits<H> is specialized, so use its value_type.
static_assert( check_alias<H, std::iterator_traits<H>::value_type> );
struct I
{
using value_type = I;
};
// iterator_traits<I> is not specialized, and no standard specialization
// matches, so use readable_traits.
static_assert( check_alias<I, std::readable_traits<I>::value_type> );
struct J
{
using iterator_category = std::input_iterator_tag;
using difference_type = int;
using value_type = char;
using reference = value_type&;
};
// iterator_traits<J> matches constrained specialization in the library,
// so use its value_type.
static_assert( check_alias<J, int> );
// Copyright (C) 2019 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 compile { target c++2a } }
#include <iterator>
static_assert( std::contiguous_iterator<int*> );
static_assert( std::contiguous_iterator<const int*> );
static_assert( std::contiguous_iterator<void**> );
static_assert( ! std::contiguous_iterator<void*> );
static_assert( ! std::contiguous_iterator<const void*> );
static_assert( ! std::contiguous_iterator<volatile void*> );
static_assert( ! std::contiguous_iterator<void(*)()> );
static_assert( ! std::contiguous_iterator<void(*)()> );
struct A;
static_assert( ! std::contiguous_iterator<void(A::*)()> );
static_assert( ! std::contiguous_iterator<int A::*> );
// Copyright (C) 2019 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 compile { target c++2a } }
#include <iterator>
static_assert( std::is_empty_v<std::contiguous_iterator_tag> );
static_assert( std::is_trivially_copy_constructible_v<std::contiguous_iterator_tag> );
static_assert( std::is_base_of_v<std::random_access_iterator_tag,
std::contiguous_iterator_tag> );
static_assert( std::is_convertible_v<std::contiguous_iterator_tag*,
std::random_access_iterator_tag*> );
static_assert( ! std::is_same_v<std::iterator_traits<int*>::iterator_category,
std::contiguous_iterator_tag> );
static_assert( std::is_same_v<std::iterator_traits<int*>::iterator_concept,
std::contiguous_iterator_tag> );
// Copyright (C) 2019 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>
struct X
{
int value;
constexpr X(int i) : value(i) { }
X(const X&) = default;
X& operator=(const X&) = default;
constexpr X(X&& x)
: value(x.value)
{
x.value = -2;
}
constexpr X& operator=(X&& x)
{
value = x.value;
x.value = -1;
return *this;
}
};
constexpr bool
test_X(int i, int j)
{
X x1{i}, x2{j};
std::ranges::iter_move(&x1); // no-op
x1 = std::ranges::iter_move(&x2);
return x1.value == j && x2.value == -1;
}
static_assert( test_X(1, 2) );
void
test01()
{
VERIFY( test_X(3, 4) );
}
int
main()
{
test01();
}
// Copyright (C) 2019 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>
struct X
{
int value;
constexpr X(int i) : value(i) { }
X(const X&) = default;
X& operator=(const X&) = default;
constexpr X& operator=(X&& x)
{
value = x.value;
x.value = -1;
return *this;
}
};
constexpr bool
test_X(int i, int j)
{
X x1{i}, x2{j};
std::ranges::iter_swap(&x1, &x2);
return x1.value == j && x2.value == i;
}
static_assert( test_X(1, 2) );
void
test01()
{
VERIFY( test_X(3, 4) );
}
int
main()
{
test01();
}
// Copyright (C) 2019 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 compile { target c++2a } }
// { dg-require-normal-namespace "" }
#include <iterator>
#include "./synopsis_c++17.cc"
namespace std
{
template<class> struct incrementable_traits;
template<class> struct readable_traits;
struct contiguous_iterator_tag;
namespace ranges
{
template<input_or_output_iterator I, sentinel_for<I> S>
constexpr iter_difference_t<I> distance(I first, S last);
template<range R>
constexpr range_difference_t<R> distance(R&& r);
template<input_or_output_iterator I>
constexpr I next(I x);
template<input_or_output_iterator I>
constexpr I next(I x, iter_difference_t<I> n);
template<input_or_output_iterator I, sentinel_for<I> S>
constexpr I next(I x, S bound);
template<input_or_output_iterator I, sentinel_for<I> S>
constexpr I next(I x, iter_difference_t<I> n, S bound);
template<bidirectional_iterator I>
constexpr I prev(I x);
template<bidirectional_iterator I>
constexpr I prev(I x, iter_difference_t<I> n);
template<bidirectional_iterator I>
constexpr I prev(I x, iter_difference_t<I> n, I bound);
}
template<semiregular S> class move_sentinel;
template<input_or_output_iterator I, sentinel_for<I> S>
requires (!same_as<I, S>)
class common_iterator;
template<class I, class S>
struct incrementable_traits<common_iterator<I, S>>;
template<input_iterator I, class S>
struct iterator_traits<common_iterator<I, S>>;
struct default_sentinel_t;
template<input_or_output_iterator I> class counted_iterator;
template<class I>
struct incrementable_traits<counted_iterator<I>>;
template<input_iterator I>
struct iterator_traits<counted_iterator<I>>;
struct unreachable_sentinel_t;
}
namespace __gnu_test
{
// customization points
constexpr auto* iter_move = &std::ranges::iter_move;
constexpr auto* iter_swap = &std::ranges::iter_swap;
// sized sentinels
constexpr bool const* disable_sized_sentinel
= &std::disable_sized_sentinel<void, void>;
// default sentinels
constexpr std::default_sentinel_t const* default_sentinel
= &std::default_sentinel;
// unreachable sentinels
constexpr std::unreachable_sentinel_t const* unreachable_sentinel
= &std::unreachable_sentinel;
}
// Copyright (C) 2019 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>
#include <testsuite_iterators.h>
using __gnu_test::test_range;
using __gnu_test::random_access_iterator_wrapper;
using __gnu_test::bidirectional_iterator_wrapper;
using __gnu_test::forward_iterator_wrapper;
using __gnu_test::input_iterator_wrapper;
using __gnu_test::output_iterator_wrapper;
void
test01()
{
int a[2] = { };
test_range<int, random_access_iterator_wrapper> r(a);
auto iter = r.begin();
std::ranges::advance(iter, 1);
VERIFY( iter != r.begin() );
VERIFY( iter != r.end() );
std::ranges::advance(iter, 1);
VERIFY( iter == r.end() );
std::ranges::advance(iter, -2);
VERIFY( iter == r.begin() );
std::ranges::advance(iter, r.begin() + 1);
VERIFY( iter != r.begin() );
VERIFY( iter != r.end() );
std::ranges::advance(iter, r.begin());
VERIFY( iter == r.begin() );
std::ranges::advance(iter, 99, r.end());
VERIFY( iter == r.end() );
std::ranges::advance(iter, -222, r.begin());
VERIFY( iter == r.begin() );
}
void
test02()
{
int a[2] = { };
test_range<int, bidirectional_iterator_wrapper> r(a);
auto iter = r.begin();
std::ranges::advance(iter, 1);
VERIFY( iter != r.begin() );
VERIFY( iter != r.end() );
std::ranges::advance(iter, 1);
VERIFY( iter == r.end() );
std::ranges::advance(iter, -2);
VERIFY( iter == r.begin() );
auto iter1 = r.begin();
++iter1;
std::ranges::advance(iter, iter1);
VERIFY( iter != r.begin() );
VERIFY( iter != r.end() );
std::ranges::advance(iter, r.begin());
VERIFY( iter == r.begin() );
std::ranges::advance(iter, 99, r.end());
VERIFY( iter == r.end() );
std::ranges::advance(iter, -222, r.begin());
VERIFY( iter == r.begin() );
}
void
test03()
{
int a[2] = { };
test_range<int, forward_iterator_wrapper> r(a);
auto iter = r.begin();
std::ranges::advance(iter, 1);
VERIFY( iter != r.begin() );
VERIFY( iter != r.end() );
std::ranges::advance(iter, 1);
std::ranges::advance(iter, 0);
VERIFY( iter == r.end() );
std::ranges::advance(iter, 0);
VERIFY( iter == r.end() );
auto iter1 = r.begin();
++iter1;
std::ranges::advance(iter, iter1);
VERIFY( iter != r.begin() );
VERIFY( iter != r.end() );
std::ranges::advance(iter, r.end());
VERIFY( iter == r.end() );
std::ranges::advance(iter, r.end());
VERIFY( iter == r.end() );
std::ranges::advance(iter, 99, r.end());
VERIFY( iter == r.end() );
std::ranges::advance(iter, 99, r.end());
VERIFY( iter == r.end() );
iter = r.begin();
std::ranges::advance(iter, 99, r.end());
VERIFY( iter == r.end() );
std::ranges::advance(iter, 99, r.end());
VERIFY( iter == r.end() );
}
void
test04()
{
int a[2] = { };
test_range<int, input_iterator_wrapper> r(a);
auto iter = r.begin();
std::ranges::advance(iter, 1);
VERIFY( iter != r.end() );
std::ranges::advance(iter, 1);
std::ranges::advance(iter, 0);
VERIFY( iter == r.end() );
std::ranges::advance(iter, 0);
VERIFY( iter == r.end() );
test_range<int, input_iterator_wrapper> r2(a);
iter = r2.begin();
++iter;
const auto iter1 = iter;
std::ranges::advance(iter, iter1);
VERIFY( iter == iter1 );
VERIFY( iter != r2.end() );
std::ranges::advance(iter, r2.end());
VERIFY( iter == r2.end() );
std::ranges::advance(iter, r2.end());
VERIFY( iter == r2.end() );
std::ranges::advance(iter, 99, r2.end());
VERIFY( iter == r2.end() );
std::ranges::advance(iter, 99, r2.end());
VERIFY( iter == r2.end() );
test_range<int, input_iterator_wrapper> r3(a);
iter = r3.begin();
std::ranges::advance(iter, 99, r3.end());
VERIFY( iter == r3.end() );
std::ranges::advance(iter, 99, r3.end());
VERIFY( iter == r3.end() );
}
void
test05()
{
int a[2] = { };
test_range<int, output_iterator_wrapper> r(a);
auto iter = r.begin();
std::ranges::advance(iter, 1);
VERIFY( iter != r.end() );
std::ranges::advance(iter, 1);
std::ranges::advance(iter, 0);
VERIFY( iter == r.end() );
std::ranges::advance(iter, 0);
VERIFY( iter == r.end() );
test_range<int, output_iterator_wrapper> r2(a);
iter = r2.begin();
++iter;
std::ranges::advance(iter, r2.end());
VERIFY( iter == r2.end() );
std::ranges::advance(iter, r2.end());
VERIFY( iter == r2.end() );
std::ranges::advance(iter, 99, r2.end());
VERIFY( iter == r2.end() );
std::ranges::advance(iter, 99, r2.end());
VERIFY( iter == r2.end() );
test_range<int, output_iterator_wrapper> r3(a);
iter = r3.begin();
std::ranges::advance(iter, 99, r3.end());
VERIFY( iter == r3.end() );
std::ranges::advance(iter, 99, r3.end());
VERIFY( iter == r3.end() );
}
int
main()
{
test01();
test02();
test03();
test04();
test05();
}
// Copyright (C) 2019 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>
#include <testsuite_iterators.h>
using __gnu_test::test_range;
using __gnu_test::test_sized_range;
using __gnu_test::random_access_iterator_wrapper;
using __gnu_test::bidirectional_iterator_wrapper;
using __gnu_test::forward_iterator_wrapper;
using __gnu_test::input_iterator_wrapper;
using __gnu_test::output_iterator_wrapper;
void
test01()
{
int a[10] = { };
VERIFY( std::ranges::distance(a) == 10 );
test_range<int, random_access_iterator_wrapper> c(a);
VERIFY( std::ranges::distance(c) == 10 );
auto b = c.begin(), e = c.end();
VERIFY( std::ranges::distance(b, e) == 10 );
VERIFY( std::ranges::distance(e, b) == -10 );
const auto cb = b, ce = e;
VERIFY( std::ranges::distance(cb, ce) == 10 );
VERIFY( std::ranges::distance(ce, cb) == -10 );
test_sized_range<int, random_access_iterator_wrapper> c2(a);
VERIFY( std::ranges::distance(c2) == 10 );
}
void
test02()
{
int a[2] = { };
VERIFY( std::ranges::distance(a) == 2 );
test_range<int, bidirectional_iterator_wrapper> c(a);
VERIFY( std::ranges::distance(c) == 2 );
auto b = c.begin(), e = c.end();
VERIFY( std::ranges::distance(b, e) == 2 );
const auto cb = b, ce = e;
VERIFY( std::ranges::distance(cb, ce) == 2 );
test_sized_range<int, bidirectional_iterator_wrapper> c2(a);
VERIFY( std::ranges::distance(c2) == 2 );
}
void
test03()
{
int a[3] = { };
test_range<int, forward_iterator_wrapper> c(a);
VERIFY( std::ranges::distance(c) == 3 );
auto b = c.begin(), e = c.end();
VERIFY( std::ranges::distance(b, e) == 3 );
const auto cb = b, ce = e;
VERIFY( std::ranges::distance(cb, ce) == 3 );
test_sized_range<int, forward_iterator_wrapper> c2(a);
VERIFY( std::ranges::distance(c2) == 3 );
}
void
test04()
{
int a[4] = { };
test_range<int, input_iterator_wrapper> c(a);
static_assert( std::ranges::range<decltype(c)> );
VERIFY( std::ranges::distance(c) == 4 );
// first call to distance has traversed the range:
VERIFY( std::ranges::distance(c) == 0 );
c = test_range<int, input_iterator_wrapper>(a);
auto b = c.begin(), e = c.end();
VERIFY( std::ranges::distance(b, e) == 4 );
test_range<int, input_iterator_wrapper> c2(a);
const auto cb = c2.begin(), ce = c2.end();
VERIFY( std::ranges::distance(cb, ce) == 4 );
test_sized_range<int, input_iterator_wrapper> c3(a);
VERIFY( std::ranges::distance(c3) == 4 );
// first call to distance just called size() without affecting the range:
VERIFY( std::ranges::distance(c3) == 4 );
}
void
test05()
{
int a[5] = { };
test_range<int, output_iterator_wrapper> c(a);
VERIFY( std::ranges::distance(c) == 5 );
test_range<int, output_iterator_wrapper> c2(a);
auto b = c2.begin();
auto e = c2.end();
VERIFY( std::ranges::distance(b, e) == 5 );
test_range<int, output_iterator_wrapper> c3(a);
const auto cb = c3.begin();
const auto ce = c3.end();
VERIFY( std::ranges::distance(cb, ce) == 5 );
test_sized_range<int, output_iterator_wrapper> c4(a);
VERIFY( std::ranges::distance(c4) == 5 );
// first call to distance just called size() without affecting the range:
VERIFY( std::ranges::distance(c4) == 5 );
}
int
main()
{
test01();
test02();
test03();
test04();
test05();
}
// Copyright (C) 2019 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>
#include <testsuite_iterators.h>
using __gnu_test::test_range;
using __gnu_test::random_access_iterator_wrapper;
using __gnu_test::bidirectional_iterator_wrapper;
using __gnu_test::forward_iterator_wrapper;
using __gnu_test::input_iterator_wrapper;
using __gnu_test::output_iterator_wrapper;
void
test01()
{
int a[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
test_range<int, random_access_iterator_wrapper> r(a);
auto begin = r.begin();
auto end = r.end();
VERIFY( *std::ranges::next(begin) == 1 );
VERIFY( std::ranges::next(begin, 0) == begin );
VERIFY( *std::ranges::next(begin, 1) == 1 );
VERIFY( *std::ranges::next(begin, 3) == 3 );
VERIFY( *std::ranges::next(end, -4) == 6 );
VERIFY( std::ranges::next(begin, begin) == begin );
VERIFY( std::ranges::next(begin, end) == end );
VERIFY( std::ranges::next(end, end) == end );
VERIFY( std::ranges::next(end, begin) == begin );
VERIFY( std::ranges::next(begin, 0, begin) == begin );
VERIFY( std::ranges::next(begin, 5, begin) == begin );
VERIFY( std::ranges::next(begin, -5, begin) == begin );
VERIFY( std::ranges::next(begin, 0, end) == begin );
VERIFY( *std::ranges::next(begin, 5, end) == 5 );
VERIFY( std::ranges::next(begin, 55, end) == end );
VERIFY( std::ranges::next(end, 0, end) == end );
VERIFY( std::ranges::next(end, -5, end) == end );
VERIFY( std::ranges::next(end, -55, end) == end );
VERIFY( std::ranges::next(end, 0, begin) == end );
VERIFY( *std::ranges::next(end, -5, begin) == 5 );
VERIFY( std::ranges::next(end, -55, begin) == begin );
}
void
test02()
{
int a[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
test_range<int, bidirectional_iterator_wrapper> r(a);
auto begin = r.begin();
auto end = r.end();
VERIFY( *std::ranges::next(begin) == 1 );
VERIFY( std::ranges::next(begin, 0) == begin );
VERIFY( *std::ranges::next(begin, 1) == 1 );
VERIFY( *std::ranges::next(begin, 3) == 3 );
VERIFY( *std::ranges::next(end, -4) == 6 );
VERIFY( std::ranges::next(begin, begin) == begin );
VERIFY( std::ranges::next(begin, end) == end );
VERIFY( std::ranges::next(end, end) == end );
VERIFY( std::ranges::next(end, begin) == begin );
VERIFY( std::ranges::next(begin, 0, begin) == begin );
VERIFY( std::ranges::next(begin, 5, begin) == begin );
VERIFY( std::ranges::next(begin, -5, begin) == begin );
VERIFY( std::ranges::next(begin, 0, end) == begin );
VERIFY( *std::ranges::next(begin, 5, end) == 5 );
VERIFY( std::ranges::next(begin, 55, end) == end );
VERIFY( std::ranges::next(end, 0, end) == end );
VERIFY( std::ranges::next(end, -5, end) == end );
VERIFY( std::ranges::next(end, -55, end) == end );
VERIFY( std::ranges::next(end, 0, begin) == end );
VERIFY( *std::ranges::next(end, -5, begin) == 5 );
VERIFY( std::ranges::next(end, -55, begin) == begin );
}
void
test03()
{
int a[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
test_range<int, forward_iterator_wrapper> r(a);
auto begin = r.begin();
auto end = r.end();
VERIFY( *std::ranges::next(begin) == 1 );
VERIFY( std::ranges::next(begin, 0) == begin );
VERIFY( *std::ranges::next(begin, 1) == 1 );
VERIFY( *std::ranges::next(begin, 3) == 3 );
VERIFY( std::ranges::next(begin, begin) == begin );
VERIFY( std::ranges::next(begin, end) == end );
VERIFY( std::ranges::next(end, end) == end );
VERIFY( std::ranges::next(begin, 0, begin) == begin );
VERIFY( std::ranges::next(begin, 5, begin) == begin );
VERIFY( std::ranges::next(begin, -5, begin) == begin );
VERIFY( std::ranges::next(begin, 0, end) == begin );
VERIFY( *std::ranges::next(begin, 5, end) == 5 );
VERIFY( std::ranges::next(begin, 55, end) == end );
VERIFY( std::ranges::next(end, 0, end) == end );
VERIFY( std::ranges::next(end, 5, end) == end );
VERIFY( std::ranges::next(end, 55, end) == end );
VERIFY( std::ranges::next(end, 0, begin) == end );
}
void
test04()
{
int a[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
test_range<int, input_iterator_wrapper> r(a);
auto begin = r.begin();
auto end = r.end();
auto iter = std::ranges::next(begin);
VERIFY( *iter == 1 );
iter = std::ranges::next(iter, 0);
VERIFY( *iter == 1 );
iter = std::ranges::next(iter, 1);
VERIFY( *iter == 2 );
iter = std::ranges::next(iter, 4);
VERIFY( *iter == 6 );
iter = std::ranges::next(iter, iter);
VERIFY( *iter == 6 );
iter = std::ranges::next(iter, end);
VERIFY( iter == end );
iter = std::ranges::next(iter, end);
VERIFY( iter == end );
test_range<int, input_iterator_wrapper> r2(a);
begin = r2.begin();
end = r2.end();
iter = std::ranges::next(begin, 0, begin);
VERIFY( *iter == 0 );
iter = std::ranges::next(begin, 5, begin);
VERIFY( *iter == 0 );
iter = std::ranges::next(begin, -5, begin);
VERIFY( *iter == 0 );
iter = std::ranges::next(begin, 0, end);
VERIFY( *iter == 0 );
iter = std::ranges::next(end, 0, begin);
VERIFY( iter == end );
iter = std::ranges::next(begin, 5, end); // invalidates begin
VERIFY( *iter == 5 );
iter = std::ranges::next(iter, 55, end);
VERIFY( iter == end );
iter = std::ranges::next(end, 0, end);
VERIFY( iter == end );
iter = std::ranges::next(end, 5, end);
VERIFY( iter == end );
}
void
test05()
{
int a[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
test_range<int, output_iterator_wrapper> r(a);
auto iter = r.begin();
auto end = r.end(); // sentinel, !same_as<decltype(iter), decltype(end)>
iter = std::ranges::next(iter);
*iter = 10;
VERIFY( a[1] == 10 );
iter = std::ranges::next(iter, 0);
iter = std::ranges::next(iter, 1);
*iter = 20;
VERIFY( a[2] == 20 );
iter = std::ranges::next(iter, 4);
iter = std::ranges::next(iter, 0);
*iter = 60;
VERIFY( a[6] == 60 );
iter = std::ranges::next(iter, end);
VERIFY( iter == end );
iter = std::ranges::next(iter, end);
VERIFY( iter == end );
test_range<int, output_iterator_wrapper> r2(a);
iter = std::ranges::next(r2.begin(), 5);
end = r2.end();
iter = std::ranges::next(iter, 0, end);
*iter = 50;
VERIFY( a[5] == 50 );
iter = std::ranges::next(iter, 2, end);
*iter = 70;
VERIFY( a[7] == 70 );
iter = std::ranges::next(iter, 5, end);
VERIFY( iter == end );
}
int
main()
{
test01();
test02();
test03();
test04();
test05();
}
// Copyright (C) 2019 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>
#include <testsuite_iterators.h>
using __gnu_test::test_range;
using __gnu_test::random_access_iterator_wrapper;
using __gnu_test::bidirectional_iterator_wrapper;
using __gnu_test::forward_iterator_wrapper;
using __gnu_test::input_iterator_wrapper;
using __gnu_test::output_iterator_wrapper;
void
test01()
{
int a[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
test_range<int, random_access_iterator_wrapper> r(a);
auto begin = r.begin();
auto end = r.end();
VERIFY( *std::ranges::prev(end) == 9 );
VERIFY( std::ranges::prev(begin, 0) == begin );
VERIFY( *std::ranges::prev(end, 1) == 9 );
VERIFY( *std::ranges::prev(end, 3) == 7 );
VERIFY( *std::ranges::prev(begin, -4) == 4 );
VERIFY( std::ranges::prev(begin, 0, begin) == begin );
VERIFY( std::ranges::prev(begin, 5, begin) == begin );
VERIFY( std::ranges::prev(begin, -5, begin) == begin );
VERIFY( std::ranges::prev(begin, 0, end) == begin );
VERIFY( *std::ranges::prev(end, 5, begin) == 5 );
VERIFY( std::ranges::prev(end, 55, begin) == begin );
VERIFY( std::ranges::prev(end, 0, end) == end );
VERIFY( std::ranges::prev(end, -5, end) == end );
VERIFY( std::ranges::prev(end, -55, end) == end );
VERIFY( std::ranges::prev(end, 0, begin) == end );
VERIFY( *std::ranges::prev(begin, -5, end) == 5 );
VERIFY( std::ranges::prev(begin, -55, end) == end );
}
void
test02()
{
int a[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
test_range<int, bidirectional_iterator_wrapper> r(a);
auto begin = r.begin();
auto end = r.end();
VERIFY( *std::ranges::prev(end) == 9 );
VERIFY( std::ranges::prev(begin, 0) == begin );
VERIFY( *std::ranges::prev(end, 1) == 9 );
VERIFY( *std::ranges::prev(end, 3) == 7 );
VERIFY( *std::ranges::prev(begin, -4) == 4 );
VERIFY( std::ranges::prev(begin, 0, begin) == begin );
VERIFY( std::ranges::prev(begin, 5, begin) == begin );
VERIFY( std::ranges::prev(begin, -5, begin) == begin );
VERIFY( std::ranges::prev(begin, 0, end) == begin );
VERIFY( *std::ranges::prev(end, 5, begin) == 5 );
VERIFY( std::ranges::prev(end, 55, begin) == begin );
VERIFY( std::ranges::prev(end, 0, end) == end );
VERIFY( std::ranges::prev(end, -5, end) == end );
VERIFY( std::ranges::prev(end, -55, end) == end );
VERIFY( std::ranges::prev(end, 0, begin) == end );
VERIFY( *std::ranges::prev(begin, -5, end) == 5 );
VERIFY( std::ranges::prev(begin, -55, end) == end );
}
template<typename T>
concept can_prev = requires(T& t) { std::ranges::prev(t); }
|| requires(T& t) { std::ranges::prev(t, 1); }
|| requires(T& t) { std::ranges::prev(t, 1, t); };
static_assert( !can_prev<forward_iterator_wrapper<int>> );
static_assert( !can_prev<input_iterator_wrapper<int>> );
static_assert( !can_prev<output_iterator_wrapper<int>> );
int
main()
{
test01();
test02();
}
......@@ -28,9 +28,10 @@ namespace std
using __gnu_test::NonDefaultConstructible;
typedef NonDefaultConstructible value_type;
typedef value_type* input_iterator;
typedef value_type* output_iterator;
typedef value_type* input_iterator_type;
typedef value_type* output_iterator_type;
template
output_iterator adjacent_difference(input_iterator, input_iterator, output_iterator);
template output_iterator_type
adjacent_difference(input_iterator_type, input_iterator_type,
output_iterator_type);
}
......@@ -28,9 +28,10 @@ namespace std
using __gnu_test::pod_int;
typedef pod_int value_type;
typedef value_type* input_iterator;
typedef value_type* output_iterator;
typedef value_type* input_iterator_type;
typedef value_type* output_iterator_type;
template
output_iterator adjacent_difference(input_iterator, input_iterator, output_iterator);
template output_iterator_type
adjacent_difference(input_iterator_type, input_iterator_type,
output_iterator_type);
}
......@@ -28,8 +28,9 @@ namespace std
using __gnu_test::NonDefaultConstructible;
typedef NonDefaultConstructible value_type;
typedef value_type* input_iterator;
typedef value_type* output_iterator;
typedef value_type* input_iterator_type;
typedef value_type* output_iterator_type;
template output_iterator partial_sum(input_iterator, input_iterator, output_iterator);
template output_iterator_type
partial_sum(input_iterator_type, input_iterator_type, output_iterator_type);
}
......@@ -28,8 +28,9 @@ namespace std
using __gnu_test::pod_int;
typedef pod_int value_type;
typedef value_type* input_iterator;
typedef value_type* output_iterator;
typedef value_type* input_iterator_type;
typedef value_type* output_iterator_type;
template output_iterator partial_sum(input_iterator, input_iterator, output_iterator);
template output_iterator_type
partial_sum(input_iterator_type, input_iterator_type, output_iterator_type);
}
......@@ -64,4 +64,6 @@ std::move_iterator<int*> mi;
std::istream_iterator<int> isi;
std::ostream_iterator<int> osi(os());
std::istreambuf_iterator<char> isbi;
#include <ostream>
std::ostreambuf_iterator<char> osbi(os());
// Copyright (C) 2019 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> // N.B. should be <ranges>
#include <testsuite_hooks.h>
#include <testsuite_iterators.h>
using std::same_as;
void
test01()
{
int a[2] = {};
static_assert(same_as<decltype(std::ranges::begin(a)), decltype(a + 0)>);
static_assert(noexcept(std::ranges::begin(a)));
VERIFY( std::ranges::begin(a) == (a + 0) );
constexpr long b[2] = { };
static_assert( std::ranges::begin(b) == (b + 0) );
}
void
test02()
{
using __gnu_test::test_range;
using __gnu_test::random_access_iterator_wrapper;
using __gnu_test::input_iterator_wrapper;
using __gnu_test::output_iterator_wrapper;
int a[] = { 0, 1 };
test_range<int, random_access_iterator_wrapper> r(a);
static_assert(same_as<decltype(std::ranges::begin(r)), decltype(r.begin())>);
VERIFY( std::ranges::begin(r) == r.begin() );
test_range<int, input_iterator_wrapper> i(a);
static_assert(same_as<decltype(std::ranges::begin(i)), decltype(i.begin())>);
VERIFY( std::ranges::begin(i) == i.begin() );
test_range<int, output_iterator_wrapper> o(a);
static_assert(same_as<decltype(std::ranges::begin(o)), decltype(o.begin())>);
*std::ranges::begin(o) = 99;
VERIFY( a[0] == 99 );
}
struct R
{
int a[4] = { 0, 1, 2, 3 };
friend int* begin(R& r) { return r.a + 0; }
friend int* begin(R&& r) { return r.a + 1; }
friend const int* begin(const R& r) noexcept { return r.a + 2; }
friend const int* begin(const R&& r) noexcept { return r.a + 3; }
};
void
test03()
{
R r;
const R& c = r;
static_assert(same_as<decltype(std::ranges::begin(r)), decltype(begin(r))>);
static_assert(!noexcept(std::ranges::begin(r)));
VERIFY( std::ranges::begin(r) == begin(r) );
static_assert(same_as<decltype(std::ranges::begin(std::move(r))),
decltype(begin(std::move(r)))>);
static_assert(!noexcept(std::ranges::begin(std::move(r))));
VERIFY( std::ranges::begin(std::move(r)) == begin(std::move(r)) );
static_assert(same_as<decltype(std::ranges::begin(c)), decltype(begin(c))>);
static_assert(noexcept(std::ranges::begin(c)));
VERIFY( std::ranges::begin(c) == begin(c) );
static_assert(same_as<decltype(std::ranges::begin(std::move(c))),
decltype(begin(std::move(c)))>);
static_assert(noexcept(std::ranges::begin(std::move(c))));
VERIFY( std::ranges::begin(std::move(c)) == begin(std::move(c)) );
}
struct RR
{
short s = 0;
long l = 0;
int a[4] = { 0, 1, 2, 3 };
short* begin() noexcept { return &s; }
const long* begin() const { return &l; }
friend int* begin(RR& r) { return r.a + 0; }
friend int* begin(RR&& r) { return r.a + 1; }
friend const int* begin(const RR& r) { return r.a + 2; }
friend const int* begin(const RR&& r) noexcept { return r.a + 3; }
};
void
test04()
{
RR r;
const RR& c = r;
VERIFY( std::ranges::begin(r) == &r.s );
static_assert(noexcept(std::ranges::begin(r)));
VERIFY( std::ranges::begin(std::move(r)) == r.a + 1 );
static_assert(!noexcept(std::ranges::begin(std::move(r))));
VERIFY( std::ranges::begin(c) == &r.l );
static_assert(!noexcept(std::ranges::begin(c)));
VERIFY( std::ranges::begin(std::move(c)) == r.a + 3 );
static_assert(noexcept(std::ranges::begin(std::move(c))));
}
int
main()
{
test01();
test02();
test03();
test04();
}
// Copyright (C) 2019 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> // N.B. should be <ranges>
#include <testsuite_hooks.h>
using std::same_as;
void
test01()
{
int a[2] = {};
static_assert(same_as<decltype(std::ranges::cbegin(a)), const int*>);
static_assert(noexcept(std::ranges::cbegin(a)));
VERIFY( std::ranges::cbegin(a) == (a + 0) );
constexpr long b[2] = {};
static_assert( std::ranges::cbegin(b) == (b + 0) );
}
struct R
{
int a[4] = { 0, 1, 2, 3 };
friend int* begin(R& r) { return r.a + 0; }
friend int* begin(R&& r) { return r.a + 1; }
friend const int* begin(const R& r) noexcept { return r.a + 2; }
friend const int* begin(const R&& r) noexcept { return r.a + 3; }
};
void
test03()
{
R r;
const R& c = r;
VERIFY(std::ranges::cbegin(r) == std::ranges::begin(c));
VERIFY(std::ranges::cbegin(std::move(r)) == std::ranges::begin(std::move(c)));
VERIFY(std::ranges::cbegin(c) == std::ranges::begin(c));
VERIFY(std::ranges::cbegin(std::move(c)) == std::ranges::begin(std::move(c)));
}
struct RR
{
short s = 0;
long l = 0;
int a[4] = { 0, 1, 2, 3 };
short* begin() noexcept { return &s; }
const long* begin() const { return &l; }
friend int* begin(RR& r) { return r.a + 0; }
friend int* begin(RR&& r) { return r.a + 1; }
friend const int* begin(const RR& r) { return r.a + 2; }
friend const int* begin(const RR&& r) noexcept { return r.a + 3; }
};
void
test04()
{
RR r;
const RR& c = r;
VERIFY(std::ranges::cbegin(r) == std::ranges::begin(c));
VERIFY(std::ranges::cbegin(std::move(r)) == std::ranges::begin(std::move(c)));
VERIFY(std::ranges::cbegin(c) == std::ranges::begin(c));
VERIFY(std::ranges::cbegin(std::move(c)) == std::ranges::begin(std::move(c)));
}
int
main()
{
test01();
test03();
test04();
}
// Copyright (C) 2019 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()
{
struct R
{
int i = 0;
int j = 0;
int* data() { return &j; }
const R* data() const noexcept { return nullptr; }
};
R r;
const R& c = r;
VERIFY( std::ranges::cdata(r) == (R*)nullptr );
static_assert( noexcept(std::ranges::cdata(r)) );
VERIFY( std::ranges::cdata(c) == (R*)nullptr );
static_assert( noexcept(std::ranges::cdata(c)) );
}
void
test02()
{
int a[] = { 0, 1 };
VERIFY( std::ranges::cdata(a) == a + 0 );
}
struct R
{
long l = 0;
int* data() const { return nullptr; }
friend long* begin(R&& r) { return &r.l; }
friend const long* begin(const R&& r) { return &r.l + 1; }
};
void
test03()
{
R r;
const R& c = r;
VERIFY( std::ranges::cdata(std::move(r)) == std::ranges::data(std::move(c)) );
VERIFY( std::ranges::cdata(std::move(c)) == std::ranges::data(std::move(c)) );
}
int
main()
{
test01();
test02();
test03();
}
// Copyright (C) 2019 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> // N.B. should be <ranges>
#include <testsuite_hooks.h>
using std::same_as;
void
test01()
{
int a[2] = {};
static_assert(same_as<decltype(std::ranges::cend(a)), const int*>);
static_assert(noexcept(std::ranges::cend(a)));
VERIFY( std::ranges::cend(a) == (a + 2) );
}
struct R
{
int a[4] = { 0, 1, 2, 3 };
const int* begin() const { return nullptr; }
friend const int* begin(const R&& r) noexcept { return nullptr; }
// Should be ignored because it doesn't return a sentinel for int*
const long* end() const { return nullptr; }
friend int* end(R& r) { return r.a + 0; }
friend int* end(R&& r) { return r.a + 1; }
friend const int* end(const R& r) noexcept { return r.a + 2; }
friend const int* end(const R&& r) noexcept { return r.a + 3; }
};
void
test03()
{
R r;
const R& c = r;
VERIFY( std::ranges::cend(r) == std::ranges::end(c) );
VERIFY( std::ranges::cend(std::move(r)) == std::ranges::end(std::move(c)) );
VERIFY( std::ranges::cend(c) == std::ranges::end(c) );
VERIFY( std::ranges::cend(std::move(c)) == std::ranges::end(std::move(c)) );
}
struct RR
{
short s = 0;
long l = 0;
int a[4] = { 0, 1, 2, 3 };
const void* begin() const { return nullptr; }
friend const void* begin(const RR&&) noexcept { return nullptr; }
short* end() noexcept { return &s; }
const long* end() const { return &l; }
friend int* end(RR&) { throw 1; }
friend int* end(RR&& r) { return r.a + 1; }
friend const int* end(const RR&) { throw 1; }
friend const int* end(const RR&& r) noexcept { return r.a + 3; }
};
void
test04()
{
RR r;
const RR& c = r;
VERIFY( std::ranges::cend(r) == std::ranges::end(c) );
VERIFY( std::ranges::cend(std::move(r)) == std::ranges::end(std::move(c)) );
VERIFY( std::ranges::cend(c) == std::ranges::end(c) );
VERIFY( std::ranges::cend(std::move(c)) == std::ranges::end(std::move(c)) );
}
int
main()
{
test01();
test03();
test04();
}
// Copyright (C) 2019 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>
#include <testsuite_iterators.h>
struct R1
{
int i = 0;
int j = 0;
const int* rbegin() const { return &i; }
friend const int* rbegin(const R1&& r) { return &r.j; }
};
void
test01()
{
R1 r;
const R1& c = r;
VERIFY( std::ranges::crbegin(r) == std::ranges::rbegin(c) );
VERIFY( std::ranges::crbegin(std::move(r)) == std::ranges::rbegin(std::move(c)) );
VERIFY( std::ranges::crbegin(c) == std::ranges::rbegin(c) );
VERIFY( std::ranges::crbegin(std::move(c)) == std::ranges::rbegin(std::move(c)) );
}
struct R2
{
int a[2] = { };
long l[2] = { };
const int* begin() const { return a; }
const int* end() const { return a + 2; }
friend const long* begin(const R2&& r) { return r.l; }
friend const long* end(const R2&& r) { return r.l + 2; }
};
void
test02()
{
R2 r;
const R2& c = r;
VERIFY( std::ranges::crbegin(r) == std::ranges::rbegin(c) );
VERIFY( std::ranges::crbegin(std::move(r)) == std::ranges::rbegin(std::move(c)) );
VERIFY( std::ranges::crbegin(c) == std::ranges::rbegin(c) );
VERIFY( std::ranges::crbegin(std::move(c)) == std::ranges::rbegin(std::move(c)) );
}
int
main()
{
test01();
test02();
}
// Copyright (C) 2019 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>
#include <testsuite_iterators.h>
struct R1
{
int i = 0;
int j = 0;
constexpr const int* rbegin() const { return &i; }
constexpr const int* rend() const { return &i + 1; }
friend constexpr const int* rbegin(const R1&& r) { return &r.j; }
friend constexpr const int* rend(const R1&& r) { return &r.j + 1; }
};
void
test01()
{
R1 r;
const R1& c = r;
VERIFY( std::ranges::crend(r) == std::ranges::rend(c) );
VERIFY( std::ranges::crend(std::move(r)) == std::ranges::rend(std::move(c)) );
VERIFY( std::ranges::crend(c) == std::ranges::rend(c) );
VERIFY( std::ranges::crend(std::move(c)) == std::ranges::rend(std::move(c)) );
}
struct R2
{
int a[2] = { };
long l[2] = { };
const int* begin() const { return a; }
const int* end() const { return a + 2; }
friend const long* begin(const R2&& r) { return r.l; }
friend const long* end(const R2&& r) { return r.l + 2; }
};
void
test02()
{
R2 r;
const R2& c = r;
VERIFY( std::ranges::crend(r) == std::ranges::rend(c) );
VERIFY( std::ranges::crend(std::move(r)) == std::ranges::rend(std::move(c)) );
VERIFY( std::ranges::crend(c) == std::ranges::rend(c) );
VERIFY( std::ranges::crend(std::move(c)) == std::ranges::rend(std::move(c)) );
}
struct R3
{
int i = 0;
const int* rbegin() const noexcept { return &i + 1; }
const long* rend() const noexcept { return nullptr; } // not a sentinel for rbegin()
friend const long* rbegin(const R3&) noexcept { return nullptr; }
friend const int* rend(const R3& r) { return &r.i; }
};
void
test03()
{
R3 r;
const R3& c = r;
VERIFY( std::ranges::crend(r) == std::ranges::rend(c) );
static_assert( !noexcept(std::ranges::crend(r)) );
VERIFY( std::ranges::crend(c) == std::ranges::rend(c) );
static_assert( !noexcept(std::ranges::crend(c)) );
}
void
test04()
{
int a[2] = { };
const auto& c = a;
VERIFY( std::ranges::crend(a) == std::ranges::rend(c) );
VERIFY( std::ranges::crend(c) == std::ranges::rend(c) );
}
int
main()
{
test01();
test02();
test03();
test04();
}
// Copyright (C) 2019 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>
#include <testsuite_iterators.h>
void
test01()
{
struct R
{
int i = 0;
int j = 0;
int* data() { return &j; }
const R* data() const noexcept { return nullptr; }
};
R r;
const R& c = r;
VERIFY( std::ranges::data(r) == &r.j );
static_assert( !noexcept(std::ranges::data(r)) );
VERIFY( std::ranges::data(c) == (R*)nullptr );
static_assert( noexcept(std::ranges::data(c)) );
}
void
test02()
{
int a[] = { 0, 1 };
VERIFY( std::ranges::data(a) == a + 0 );
__gnu_test::test_range<int, __gnu_test::contiguous_iterator_wrapper> r(a);
VERIFY( std::ranges::data(r) == std::to_address(std::ranges::begin(r)) );
}
struct R3
{
long l = 0;
int* data() const { return nullptr; }
friend long* begin(R3&& r) { return &r.l; }
friend const long* begin(const R3&& r) { return &r.l + 1; }
};
void
test03()
{
R3 r;
const R3& c = r;
VERIFY( std::ranges::data(std::move(r)) == std::to_address(std::ranges::begin(std::move(r))) );
VERIFY( std::ranges::data(std::move(c)) == std::to_address(std::ranges::begin(std::move(c))) );
}
int
main()
{
test01();
test02();
test03();
}
// Copyright (C) 2019 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> // N.B. should be <ranges>
#include <testsuite_hooks.h>
#include <testsuite_iterators.h>
using std::same_as;
void
test01()
{
struct R
{
constexpr int empty() const & { return 0; }
constexpr const void* empty() const && { return this; }
};
constexpr R r;
static_assert( !std::ranges::empty(r) );
static_assert( same_as<decltype(std::ranges::empty(r)), bool> );
static_assert( std::ranges::empty(std::move(r)) );
static_assert( same_as<decltype(std::ranges::empty(std::move(r))), bool> );
}
void
test02()
{
using __gnu_test::test_range;
using __gnu_test::test_sized_range;
using __gnu_test::random_access_iterator_wrapper;
using __gnu_test::forward_iterator_wrapper;
using __gnu_test::input_iterator_wrapper;
using __gnu_test::output_iterator_wrapper;
int a[] = { 0, 1 };
VERIFY( !std::ranges::empty(a) );
test_range<int, random_access_iterator_wrapper> r(a);
VERIFY( !std::ranges::empty(r) );
test_range<int, forward_iterator_wrapper> i(a);
VERIFY( !std::ranges::empty(i) );
test_sized_range<int, random_access_iterator_wrapper> sr(a);
VERIFY( !std::ranges::empty(sr) );
test_sized_range<int, input_iterator_wrapper> si(a);
VERIFY( !std::ranges::empty(si) );
test_sized_range<int, output_iterator_wrapper> so(a);
VERIFY( !std::ranges::empty(so) );
}
int
main()
{
test01();
test02();
}
// Copyright (C) 2019 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> // N.B. should be <ranges>
#include <testsuite_hooks.h>
#include <testsuite_iterators.h>
using std::same_as;
void
test01()
{
int a[2] = {};
static_assert(same_as<decltype(std::ranges::end(a)), decltype(a + 2)>);
static_assert(noexcept(std::ranges::end(a)));
VERIFY( std::ranges::end(a) == (a + 2) );
}
void
test02()
{
using __gnu_test::test_range;
using __gnu_test::random_access_iterator_wrapper;
using __gnu_test::input_iterator_wrapper;
using __gnu_test::output_iterator_wrapper;
int a[] = { 0, 1 };
test_range<int, random_access_iterator_wrapper> r(a);
static_assert(same_as<decltype(std::ranges::end(r)), decltype(r.end())>);
VERIFY( std::ranges::end(r) == r.end() );
test_range<int, input_iterator_wrapper> i(a);
static_assert(same_as<decltype(std::ranges::end(i)), decltype(i.end())>);
VERIFY( std::ranges::end(i) == i.end() );
test_range<int, output_iterator_wrapper> o(a);
static_assert(same_as<decltype(std::ranges::end(o)), decltype(o.end())>);
VERIFY( std::ranges::end(o) == std::ranges::next(o.begin(), 2) );
}
struct R
{
int a[4] = { 0, 1, 2, 3 };
const int* begin() const { return nullptr; }
friend const int* begin(const R&& r) noexcept { return nullptr; }
// Should be ignored because it doesn't return a sentinel for int*
const long* end() const { return nullptr; }
friend int* end(R& r) { return r.a + 0; }
friend int* end(R&& r) { return r.a + 1; }
friend const int* end(const R& r) noexcept { return r.a + 2; }
friend const int* end(const R&& r) noexcept { return r.a + 3; }
};
void
test03()
{
R r;
const R& c = r;
static_assert(same_as<decltype(std::ranges::end(r)), decltype(end(r))>);
static_assert(!noexcept(std::ranges::end(r)));
VERIFY( std::ranges::end(r) == end(r) );
static_assert(same_as<decltype(std::ranges::end(std::move(r))),
decltype(end(std::move(r)))>);
static_assert(!noexcept(std::ranges::end(std::move(r))));
VERIFY( std::ranges::end(std::move(r)) == end(std::move(r)) );
static_assert(same_as<decltype(std::ranges::end(c)), decltype(end(c))>);
static_assert(noexcept(std::ranges::end(c)));
VERIFY( std::ranges::end(c) == end(c) );
static_assert(same_as<decltype(std::ranges::end(std::move(c))),
decltype(end(std::move(c)))>);
static_assert(noexcept(std::ranges::end(std::move(c))));
VERIFY( std::ranges::end(std::move(c)) == end(std::move(c)) );
}
struct RR
{
short s = 0;
long l = 0;
int a[4] = { 0, 1, 2, 3 };
const void* begin() const { return nullptr; }
friend const void* begin(const RR&&) noexcept { return nullptr; }
short* end() noexcept { return &s; }
const long* end() const { return &l; }
friend int* end(RR&) { throw 1; }
friend int* end(RR&& r) { return r.a + 1; }
friend const int* end(const RR&) { throw 1; }
friend const int* end(const RR&& r) noexcept { return r.a + 3; }
};
void
test04()
{
RR r;
const RR& c = r;
VERIFY( std::ranges::end(r) == &r.s );
static_assert(noexcept(std::ranges::end(r)));
VERIFY( std::ranges::end(std::move(r)) == r.a + 1 );
static_assert(!noexcept(std::ranges::end(std::move(r))));
VERIFY( std::ranges::end(c) == &r.l );
static_assert(!noexcept(std::ranges::end(c)));
VERIFY( std::ranges::end(std::move(c)) == r.a + 3 );
static_assert(noexcept(std::ranges::end(std::move(c))));
}
int
main()
{
test01();
test02();
test03();
test04();
}
// Copyright (C) 2019 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>
#include <testsuite_iterators.h>
struct R1
{
int i = 0;
int j = 0;
constexpr const int* rbegin() const { return &i; }
friend constexpr const int* rbegin(const R1&& r) { return &r.j; }
};
void
test01()
{
constexpr R1 r;
static_assert( std::ranges::rbegin(r) == &r.i );
static_assert( std::ranges::rbegin(std::move(r)) == &r.j );
}
struct R2
{
int a[2] = { };
long l[2] = { };
constexpr const int* begin() const { return a; }
constexpr const int* end() const { return a + 2; }
friend constexpr const long* begin(const R2&& r) { return r.l; }
friend constexpr const long* end(const R2&& r) { return r.l + 2; }
};
void
test02()
{
constexpr R2 r;
static_assert( std::ranges::rbegin(r)
== std::make_reverse_iterator(std::ranges::end(r)) );
static_assert( std::ranges::rbegin(std::move(r))
== std::make_reverse_iterator(std::ranges::end(std::move(r))) );
}
void
test03()
{
using __gnu_test::test_range;
using __gnu_test::bidirectional_iterator_wrapper;
int a[2] = { };
test_range<int, bidirectional_iterator_wrapper> r(a);
VERIFY( std::ranges::rbegin(r) == std::make_reverse_iterator(std::ranges::end(r)) );
}
int
main()
{
test01();
test02();
test03();
}
// Copyright (C) 2019 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>
#include <testsuite_iterators.h>
struct R1
{
int i = 0;
int j = 0;
constexpr const int* rbegin() const { return &i; }
constexpr const int* rend() const { return &i + 1; }
friend constexpr const int* rbegin(const R1&& r) { return &r.j; }
friend constexpr const int* rend(const R1&& r) { return &r.j + 1; }
};
void
test01()
{
constexpr R1 r;
static_assert( std::ranges::rend(r) == &r.i + 1 );
static_assert( std::ranges::rend(std::move(r)) == &r.j + 1 );
}
struct R2
{
int a[2] = { };
long l[2] = { };
constexpr const int* begin() const { return a; }
constexpr const int* end() const { return a + 2; }
friend constexpr const long* begin(const R2&& r) { return r.l; }
friend constexpr const long* end(const R2&& r) { return r.l + 2; }
};
void
test02()
{
constexpr R2 r;
static_assert( std::ranges::rend(r)
== std::make_reverse_iterator(std::ranges::begin(r)) );
static_assert( std::ranges::rend(std::move(r))
== std::make_reverse_iterator(std::ranges::begin(std::move(r))) );
}
struct R3
{
int i = 0;
int* rbegin() noexcept { return &i + 1; }
long* rend() noexcept { return nullptr; } // not a sentinel for rbegin()
friend long* rbegin(R3&) noexcept { return nullptr; }
friend int* rend(R3& r) { return &r.i; }
};
void
test03()
{
R3 r;
auto i1 = std::ranges::rbegin(r);
auto i2 = rend(r);
static_assert( std::sentinel_for<decltype(i2), decltype(i1)> );
// VERIFY( std::ranges::rend(r) == r.i );
// static_assert( !noexcept(std::ranges::rend(r)) );
}
void
test04()
{
using __gnu_test::test_range;
using __gnu_test::bidirectional_iterator_wrapper;
int a[2] = { };
test_range<int, bidirectional_iterator_wrapper> r(a);
VERIFY( std::ranges::rend(r) == std::make_reverse_iterator(std::ranges::begin(r)) );
}
int
main()
{
test01();
test02();
test03();
}
// Copyright (C) 2019 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>
#include <testsuite_iterators.h>
void
test01()
{
constexpr int a[10] = { };
static_assert( std::ranges::size(a) == 10 );
static_assert( noexcept(std::ranges::size(a)) );
int a2[2];
VERIFY( std::ranges::size(a2) == 2);
static_assert( noexcept(std::ranges::size(a2)) );
}
void
test02()
{
struct R
{
int size() { return 1; }
long size() const noexcept { return 2; }
};
R r;
const R& c = r;
VERIFY( std::ranges::size(r) == 1 );
static_assert( !noexcept(std::ranges::size(r)) );
VERIFY( std::ranges::size(c) == 2L );
static_assert( noexcept(std::ranges::size(c)) );
int a[3] = { };
__gnu_test::test_sized_range<int, __gnu_test::input_iterator_wrapper> ri(a);
VERIFY( std::ranges::size(ri) == 3 );
static_assert( noexcept(std::ranges::size(ri)) );
}
struct R3
{
int* size() { return nullptr; }
friend int size(R3&) noexcept { return 1; }
friend long size(const R3&) { return 2L; }
friend unsigned int size(R3&&) { return 3U; }
friend unsigned long size(const R3&&) noexcept { return 4UL; }
};
void
test03()
{
R3 r;
const R3& c = r;
VERIFY( std::ranges::size(r) == 1 );
static_assert( noexcept(std::ranges::size(r)) );
VERIFY( std::ranges::size(std::move(r)) == 3U );
static_assert( !noexcept(std::ranges::size(std::move(r))) );
VERIFY( std::ranges::size(c) == 2L );
static_assert( !noexcept(std::ranges::size(c)) );
VERIFY( std::ranges::size(std::move(c)) == 4UL );
static_assert( noexcept(std::ranges::size(std::move(c))) );
}
void
test04()
{
int a[] = { 0, 1 };
__gnu_test::test_range<int, __gnu_test::random_access_iterator_wrapper> r(a);
auto& rr = r;
VERIFY( std::ranges::size(r) == (std::ranges::end(r) - std::ranges::begin(r)) );
}
struct R5
{
int size() const noexcept { return 0; }
R5* begin() { return this; }
R5* end() { return this + 1; }
};
template<>
constexpr bool std::ranges::disable_sized_range<R5> = true;
void
test05()
{
R5 r;
VERIFY( std::ranges::size(r) == 1 );
}
int
main()
{
test01();
test02();
test03();
test04();
test05();
}
......@@ -590,5 +590,145 @@ namespace __gnu_test
size() const
{ return bounds.size(); }
};
}
#endif
#if __cplusplus > 201703L
template<typename T>
struct contiguous_iterator_wrapper
: random_access_iterator_wrapper<T>
{
using random_access_iterator_wrapper<T>::random_access_iterator_wrapper;
using iterator_concept = std::contiguous_iterator_tag;
contiguous_iterator_wrapper&
operator++()
{
random_access_iterator_wrapper<T>::operator++();
return *this;
}
contiguous_iterator_wrapper&
operator--()
{
random_access_iterator_wrapper<T>::operator--();
return *this;
}
contiguous_iterator_wrapper
operator++(int)
{
auto tmp = *this;
++*this;
return tmp;
}
contiguous_iterator_wrapper
operator--(int)
{
auto tmp = *this;
--*this;
return tmp;
}
contiguous_iterator_wrapper&
operator+=(std::ptrdiff_t n)
{
random_access_iterator_wrapper<T>::operator+=(n);
return *this;
}
friend contiguous_iterator_wrapper
operator+(contiguous_iterator_wrapper iter, std::ptrdiff_t n)
{ return iter += n; }
friend contiguous_iterator_wrapper
operator+(std::ptrdiff_t n, contiguous_iterator_wrapper iter)
{ return iter += n; }
contiguous_iterator_wrapper&
operator-=(std::ptrdiff_t n)
{ return *this += -n; }
friend contiguous_iterator_wrapper
operator-(contiguous_iterator_wrapper iter, std::ptrdiff_t n)
{ return iter -= n; }
};
// A type meeting the minimum std::range requirements
template<typename T, template<typename> class Iter>
class test_range
{
// Adds default constructor to Iter<T> if needed
struct iterator : Iter<T>
{
using Iter<T>::Iter;
iterator() : Iter<T>(nullptr, nullptr) { }
using Iter<T>::operator++;
iterator& operator++() { Iter<T>::operator++(); return *this; }
};
template<typename I>
struct sentinel
{
T* end;
friend bool operator==(const sentinel& s, const I& i)
{ return s.end == i.ptr; }
friend bool operator!=(const sentinel& s, const I& i)
{ return !(s == i); }
friend bool operator==(const I& i, const sentinel& s)
{ return s == i; }
friend bool operator!=(const I& i, const sentinel& s)
{ return !(s == i); }
};
auto
get_iterator(T* p)
{
if constexpr (std::default_constructible<Iter<T>>)
return Iter<T>(p, &bounds);
else
return iterator(p, &bounds);
}
public:
test_range(T* first, T* last) : bounds(first, last)
{ }
template<std::size_t N>
explicit
test_range(T (&arr)[N]) : test_range(arr, arr+N)
{ }
auto begin() & { return get_iterator(bounds.first); }
auto end() &
{
using I = decltype(get_iterator(bounds.last));
if constexpr (std::sentinel_for<I, I>)
return get_iterator(bounds.last);
else
return sentinel<I>{bounds.last};
}
typename Iter<T>::ContainerType bounds;
};
// A type meeting the minimum std::sized_range requirements
template<typename T, template<typename> class Iter>
struct test_sized_range : test_range<T, Iter>
{
using test_range<T, Iter>::test_range;
std::size_t size() const noexcept
{ return this->bounds.size(); }
};
#endif // C++20
} // namespace __gnu_test
#endif // _TESTSUITE_ITERATORS
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment