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
This commit is contained in:
parent
9921ac3db3
commit
6d0dff49ca
40 changed files with 4267 additions and 82 deletions
|
@ -1,5 +1,85 @@
|
|||
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 \
|
||||
|
|
828
libstdc++-v3/include/bits/iterator_concepts.h
Normal file
828
libstdc++-v3/include/bits/iterator_concepts.h
Normal file
|
@ -0,0 +1,828 @@
|
|||
// Concepts and traits for use with iterators -*- C++ -*-
|
||||
|
||||
// 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.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file bits/iterator_concepts.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{iterator}
|
||||
*/
|
||||
|
||||
#ifndef _ITERATOR_CONCEPTS_H
|
||||
#define _ITERATOR_CONCEPTS_H 1
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
#include <concepts>
|
||||
#include <bits/ptr_traits.h> // to_address
|
||||
#include <bits/range_cmp.h> // identity, ranges::less
|
||||
|
||||
#if __cpp_lib_concepts
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
struct input_iterator_tag;
|
||||
struct output_iterator_tag;
|
||||
struct forward_iterator_tag;
|
||||
struct bidirectional_iterator_tag;
|
||||
struct random_access_iterator_tag;
|
||||
struct contiguous_iterator_tag;
|
||||
|
||||
template<typename _Iterator>
|
||||
struct iterator_traits;
|
||||
|
||||
template<typename _Tp> requires is_object_v<_Tp>
|
||||
struct iterator_traits<_Tp*>;
|
||||
|
||||
template<typename _Iterator, typename>
|
||||
struct __iterator_traits;
|
||||
|
||||
namespace __detail
|
||||
{
|
||||
template<typename _Tp>
|
||||
using __with_ref = _Tp&;
|
||||
|
||||
template<typename _Tp>
|
||||
concept __can_reference = requires { typename __with_ref<_Tp>; };
|
||||
|
||||
template<typename _Tp>
|
||||
concept __dereferenceable = requires(_Tp& __t)
|
||||
{
|
||||
{ *__t } -> __can_reference;
|
||||
};
|
||||
|
||||
// FIXME: needed due to PR c++/67704
|
||||
template<__detail::__dereferenceable _Tp>
|
||||
struct __iter_ref
|
||||
{
|
||||
using type = decltype(*std::declval<_Tp&>());
|
||||
};
|
||||
} // namespace __detail
|
||||
|
||||
template<typename _Tp>
|
||||
using iter_reference_t = typename __detail::__iter_ref<_Tp>::type;
|
||||
|
||||
namespace ranges
|
||||
{
|
||||
namespace __cust_imove
|
||||
{
|
||||
template<typename _Tp>
|
||||
concept __adl_imove
|
||||
= (std::__detail::__class_or_enum<remove_reference_t<_Tp>>)
|
||||
&& requires(_Tp&& __t) { iter_move(static_cast<_Tp&&>(__t)); };
|
||||
|
||||
struct _IMove
|
||||
{
|
||||
private:
|
||||
template<typename _Tp>
|
||||
static constexpr bool
|
||||
_S_noexcept()
|
||||
{
|
||||
if constexpr (__adl_imove<_Tp>)
|
||||
return noexcept(iter_move(std::declval<_Tp>()));
|
||||
else
|
||||
return noexcept(*std::declval<_Tp>());
|
||||
}
|
||||
|
||||
public:
|
||||
template<typename _Tp>
|
||||
requires __adl_imove<_Tp> || requires(_Tp& __e) { *__e; }
|
||||
constexpr decltype(auto)
|
||||
operator()(_Tp&& __e) const
|
||||
noexcept(_S_noexcept<_Tp>())
|
||||
{
|
||||
if constexpr (__adl_imove<_Tp>)
|
||||
return iter_move(static_cast<_Tp&&>(__e));
|
||||
else if constexpr (is_reference_v<iter_reference_t<_Tp>>)
|
||||
return std::move(*__e);
|
||||
else
|
||||
return *__e;
|
||||
}
|
||||
};
|
||||
} // namespace __cust_imove
|
||||
|
||||
inline namespace __cust
|
||||
{
|
||||
inline constexpr __cust_imove::_IMove iter_move{};
|
||||
} // inline namespace __cust
|
||||
} // namespace ranges
|
||||
|
||||
namespace __detail
|
||||
{
|
||||
// FIXME: needed due to PR c++/67704
|
||||
template<__detail::__dereferenceable _Tp>
|
||||
struct __iter_rvalue_ref
|
||||
{ };
|
||||
|
||||
template<__detail::__dereferenceable _Tp>
|
||||
requires requires(_Tp& __t)
|
||||
{
|
||||
{ ranges::iter_move(__t) } -> __detail::__can_reference;
|
||||
}
|
||||
struct __iter_rvalue_ref<_Tp>
|
||||
{ using type = decltype(ranges::iter_move(std::declval<_Tp&>())); };
|
||||
|
||||
} // namespace __detail
|
||||
|
||||
template<typename _Tp>
|
||||
using iter_rvalue_reference_t
|
||||
= typename __detail::__iter_rvalue_ref<_Tp>::type;
|
||||
|
||||
template<typename> struct incrementable_traits { };
|
||||
|
||||
template<typename _Tp> requires is_object_v<_Tp>
|
||||
struct incrementable_traits<_Tp*>
|
||||
{ using difference_type = ptrdiff_t; };
|
||||
|
||||
template<typename _Iter>
|
||||
struct incrementable_traits<const _Iter>
|
||||
: incrementable_traits<_Iter> { };
|
||||
|
||||
template<typename _Tp> requires requires { typename _Tp::difference_type; }
|
||||
struct incrementable_traits<_Tp>
|
||||
{ using difference_type = typename _Tp::difference_type; };
|
||||
|
||||
template<typename _Tp>
|
||||
requires (!requires { typename _Tp::difference_type; }
|
||||
&& requires(const _Tp& __a, const _Tp& __b)
|
||||
{
|
||||
requires (!is_void_v<remove_pointer_t<_Tp>>); // PR c++/78173
|
||||
{ __a - __b } -> integral;
|
||||
})
|
||||
struct incrementable_traits<_Tp>
|
||||
{
|
||||
using difference_type
|
||||
= make_signed_t<decltype(std::declval<_Tp>() - std::declval<_Tp>())>;
|
||||
};
|
||||
|
||||
namespace __detail
|
||||
{
|
||||
// An iterator such that iterator_traits<_Iter> names a specialization
|
||||
// generated from the primary template.
|
||||
template<typename _Iter>
|
||||
concept __primary_traits_iter
|
||||
= __is_base_of(__iterator_traits<_Iter, void>, iterator_traits<_Iter>);
|
||||
|
||||
template<typename _Iter, typename _Tp>
|
||||
struct __iter_traits_impl
|
||||
{ using type = iterator_traits<_Iter>; };
|
||||
|
||||
template<typename _Iter, typename _Tp>
|
||||
requires __primary_traits_iter<_Iter>
|
||||
struct __iter_traits_impl<_Iter, _Tp>
|
||||
{ using type = _Tp; };
|
||||
|
||||
// ITER_TRAITS
|
||||
template<typename _Iter, typename _Tp = _Iter>
|
||||
using __iter_traits = typename __iter_traits_impl<_Iter, _Tp>::type;
|
||||
} // namespace __detail
|
||||
|
||||
template<typename _Tp>
|
||||
using iter_difference_t = typename
|
||||
__detail::__iter_traits<_Tp, incrementable_traits<_Tp>>::difference_type;
|
||||
|
||||
namespace __detail
|
||||
{
|
||||
template<typename> struct __cond_value_type { };
|
||||
|
||||
template<typename _Tp> requires is_object_v<_Tp>
|
||||
struct __cond_value_type<_Tp>
|
||||
{ using value_type = remove_cv_t<_Tp>; };
|
||||
} // namespace __detail
|
||||
|
||||
template<typename> struct readable_traits { };
|
||||
|
||||
template<typename _Tp>
|
||||
struct readable_traits<_Tp*>
|
||||
: __detail::__cond_value_type<_Tp>
|
||||
{ };
|
||||
|
||||
template<typename _Iter> requires is_array_v<_Iter>
|
||||
struct readable_traits<_Iter>
|
||||
{ using value_type = remove_cv_t<remove_extent_t<_Iter>>; };
|
||||
|
||||
template<typename _Iter>
|
||||
struct readable_traits<const _Iter>
|
||||
: readable_traits<_Iter>
|
||||
{ };
|
||||
|
||||
template<typename _Tp> requires requires { typename _Tp::value_type; }
|
||||
struct readable_traits<_Tp>
|
||||
: __detail::__cond_value_type<typename _Tp::value_type>
|
||||
{ };
|
||||
|
||||
template<typename _Tp> requires requires { typename _Tp::element_type; }
|
||||
struct readable_traits<_Tp>
|
||||
: __detail::__cond_value_type<typename _Tp::element_type>
|
||||
{ };
|
||||
|
||||
template<typename _Tp>
|
||||
using iter_value_t = typename
|
||||
__detail::__iter_traits<_Tp, readable_traits<_Tp>>::value_type;
|
||||
|
||||
namespace __detail
|
||||
{
|
||||
template<typename _Iter>
|
||||
concept __cpp17_iterator = copyable<_Iter>
|
||||
&& requires(_Iter __it)
|
||||
{
|
||||
{ *__it } -> __can_reference;
|
||||
{ ++__it } -> same_as<_Iter&>;
|
||||
{ *__it++ } -> __can_reference;
|
||||
};
|
||||
|
||||
template<typename _Iter>
|
||||
concept __cpp17_input_iterator = __cpp17_iterator<_Iter>
|
||||
&& equality_comparable<_Iter>
|
||||
&& requires(_Iter __it)
|
||||
{
|
||||
typename incrementable_traits<_Iter>::difference_type;
|
||||
typename readable_traits<_Iter>::value_type;
|
||||
typename common_reference_t<iter_reference_t<_Iter>&&,
|
||||
typename readable_traits<_Iter>::value_type&>;
|
||||
typename common_reference_t<decltype(*__it++)&&,
|
||||
typename readable_traits<_Iter>::value_type&>;
|
||||
requires signed_integral<typename incrementable_traits<_Iter>::difference_type>;
|
||||
};
|
||||
|
||||
template<typename _Iter>
|
||||
concept __cpp17_fwd_iterator = __cpp17_input_iterator<_Iter>
|
||||
&& constructible_from<_Iter>
|
||||
&& is_lvalue_reference_v<iter_reference_t<_Iter>>
|
||||
&& same_as<remove_cvref_t<iter_reference_t<_Iter>>,
|
||||
typename readable_traits<_Iter>::value_type>
|
||||
&& requires(_Iter __it)
|
||||
{
|
||||
{ __it++ } -> convertible_to<const _Iter&>;
|
||||
{ *__it++ } -> same_as<iter_reference_t<_Iter>>;
|
||||
};
|
||||
|
||||
template<typename _Iter>
|
||||
concept __cpp17_bidi_iterator = __cpp17_fwd_iterator<_Iter>
|
||||
&& requires(_Iter __it)
|
||||
{
|
||||
{ --__it } -> same_as<_Iter&>;
|
||||
{ __it-- } -> convertible_to<const _Iter&>;
|
||||
{ *__it-- } -> same_as<iter_reference_t<_Iter>>;
|
||||
};
|
||||
|
||||
template<typename _Iter>
|
||||
concept __cpp17_randacc_iterator = __cpp17_bidi_iterator<_Iter>
|
||||
&& totally_ordered<_Iter>
|
||||
&& requires(_Iter __it,
|
||||
typename incrementable_traits<_Iter>::difference_type __n)
|
||||
{
|
||||
{ __it += __n } -> same_as<_Iter&>;
|
||||
{ __it -= __n } -> same_as<_Iter&>;
|
||||
{ __it + __n } -> same_as<_Iter>;
|
||||
{ __n + __it } -> same_as<_Iter>;
|
||||
{ __it - __n } -> same_as<_Iter>;
|
||||
{ __it - __it } -> same_as<decltype(__n)>;
|
||||
{ __it[__n] } -> convertible_to<iter_reference_t<_Iter>>;
|
||||
};
|
||||
|
||||
template<typename _Iter>
|
||||
concept __iter_with_nested_types = requires {
|
||||
typename _Iter::iterator_category;
|
||||
typename _Iter::value_type;
|
||||
typename _Iter::difference_type;
|
||||
typename _Iter::reference;
|
||||
};
|
||||
|
||||
// FIXME: needed due to PR c++/92102
|
||||
template<typename _Iter>
|
||||
concept __iter_without_nested_types = !__iter_with_nested_types<_Iter>;
|
||||
|
||||
template<typename _Iter, bool __use_arrow = false>
|
||||
struct __ptr
|
||||
{ using type = void; };
|
||||
|
||||
template<typename _Iter> requires requires { typename _Iter::pointer; }
|
||||
struct __ptr<_Iter, true>
|
||||
{ using type = typename _Iter::pointer; };
|
||||
|
||||
template<typename _Iter> requires requires { typename _Iter::pointer; }
|
||||
struct __ptr<_Iter, false>
|
||||
{ using type = typename _Iter::pointer; };
|
||||
|
||||
template<typename _Iter>
|
||||
requires (!requires { typename _Iter::pointer; }
|
||||
&& requires(_Iter& __it) { __it.operator->(); })
|
||||
struct __ptr<_Iter, true>
|
||||
{ using type = decltype(std::declval<_Iter&>().operator->()); };
|
||||
|
||||
template<typename _Iter>
|
||||
struct __ref
|
||||
{ using type = iter_reference_t<_Iter>; };
|
||||
|
||||
template<typename _Iter> requires requires { typename _Iter::reference; }
|
||||
struct __ref<_Iter>
|
||||
{ using type = typename _Iter::reference; };
|
||||
|
||||
template<typename _Iter>
|
||||
struct __cat
|
||||
{ using type = input_iterator_tag; };
|
||||
|
||||
template<typename _Iter>
|
||||
requires requires { typename _Iter::iterator_category; }
|
||||
struct __cat<_Iter>
|
||||
{ using type = typename _Iter::iterator_category; };
|
||||
|
||||
template<typename _Iter>
|
||||
requires (!requires { typename _Iter::iterator_category; }
|
||||
&& __detail::__cpp17_randacc_iterator<_Iter>)
|
||||
struct __cat<_Iter>
|
||||
{ using type = random_access_iterator_tag; };
|
||||
|
||||
template<typename _Iter>
|
||||
requires (!requires { typename _Iter::iterator_category; }
|
||||
&& __detail::__cpp17_bidi_iterator<_Iter>)
|
||||
struct __cat<_Iter>
|
||||
{ using type = bidirectional_iterator_tag; };
|
||||
|
||||
template<typename _Iter>
|
||||
requires (!requires { typename _Iter::iterator_category; }
|
||||
&& __detail::__cpp17_fwd_iterator<_Iter>)
|
||||
struct __cat<_Iter>
|
||||
{ using type = forward_iterator_tag; };
|
||||
|
||||
template<typename _Iter>
|
||||
struct __diff
|
||||
{ using type = void; };
|
||||
|
||||
template<typename _Iter>
|
||||
requires requires {
|
||||
typename incrementable_traits<_Iter>::difference_type;
|
||||
}
|
||||
struct __diff<_Iter>
|
||||
{
|
||||
using type = typename incrementable_traits<_Iter>::difference_type;
|
||||
};
|
||||
|
||||
} // namespace __detail
|
||||
|
||||
template<typename _Iterator>
|
||||
requires __detail::__iter_with_nested_types<_Iterator>
|
||||
struct __iterator_traits<_Iterator, void>
|
||||
{
|
||||
using iterator_category = typename _Iterator::iterator_category;
|
||||
using value_type = typename _Iterator::value_type;
|
||||
using difference_type = typename _Iterator::difference_type;
|
||||
using pointer = typename __detail::__ptr<_Iterator>::type;
|
||||
using reference = typename _Iterator::reference;
|
||||
};
|
||||
|
||||
template<typename _Iterator>
|
||||
requires __detail::__iter_without_nested_types<_Iterator>
|
||||
&& __detail::__cpp17_input_iterator<_Iterator>
|
||||
struct __iterator_traits<_Iterator, void>
|
||||
{
|
||||
using iterator_category = typename __detail::__cat<_Iterator>::type;
|
||||
using value_type
|
||||
= typename readable_traits<_Iterator>::value_type;
|
||||
using difference_type
|
||||
= typename incrementable_traits<_Iterator>::difference_type;
|
||||
using pointer = typename __detail::__ptr<_Iterator, true>::type;
|
||||
using reference = typename __detail::__ref<_Iterator>::type;
|
||||
};
|
||||
|
||||
template<typename _Iterator>
|
||||
requires __detail::__iter_without_nested_types<_Iterator>
|
||||
&& __detail::__cpp17_iterator<_Iterator>
|
||||
struct __iterator_traits<_Iterator, void>
|
||||
{
|
||||
using iterator_category = output_iterator_tag;
|
||||
using value_type = void;
|
||||
using difference_type = typename __detail::__diff<_Iterator>::type;
|
||||
using pointer = void;
|
||||
using reference = void;
|
||||
};
|
||||
|
||||
namespace __detail
|
||||
{
|
||||
template<typename _Iter>
|
||||
struct __iter_concept_impl
|
||||
{ };
|
||||
|
||||
template<typename _Iter>
|
||||
requires requires { typename __iter_traits<_Iter>::iterator_concept; }
|
||||
struct __iter_concept_impl<_Iter>
|
||||
{ using type = typename __iter_traits<_Iter>::iterator_concept; };
|
||||
|
||||
template<typename _Iter>
|
||||
requires (!requires { typename __iter_traits<_Iter>::iterator_concept; }
|
||||
&& requires { typename __iter_traits<_Iter>::iterator_category; })
|
||||
struct __iter_concept_impl<_Iter>
|
||||
{ using type = typename __iter_traits<_Iter>::iterator_category; };
|
||||
|
||||
template<typename _Iter>
|
||||
requires (!requires { typename __iter_traits<_Iter>::iterator_concept; }
|
||||
&& !requires { typename __iter_traits<_Iter>::iterator_category; }
|
||||
&& __primary_traits_iter<_Iter>)
|
||||
struct __iter_concept_impl<_Iter>
|
||||
{ using type = random_access_iterator_tag; };
|
||||
|
||||
// ITER_TRAITS
|
||||
template<typename _Iter>
|
||||
using __iter_concept = typename __iter_concept_impl<_Iter>::type;
|
||||
} // namespace __detail
|
||||
|
||||
/// Requirements for types that are readable by applying operator*.
|
||||
template<typename _In>
|
||||
concept readable = requires
|
||||
{
|
||||
typename iter_value_t<_In>;
|
||||
typename iter_reference_t<_In>;
|
||||
typename iter_rvalue_reference_t<_In>;
|
||||
}
|
||||
&& common_reference_with<iter_reference_t<_In>&&, iter_value_t<_In>&>
|
||||
&& common_reference_with<iter_reference_t<_In>&&,
|
||||
iter_rvalue_reference_t<_In>&&>
|
||||
&& common_reference_with<iter_rvalue_reference_t<_In>&&,
|
||||
const iter_value_t<_In>&>;
|
||||
|
||||
namespace __detail
|
||||
{
|
||||
// FIXME: needed due to PR c++/67704
|
||||
template<readable _Tp>
|
||||
struct __iter_common_ref
|
||||
: common_reference<iter_reference_t<_Tp>, iter_value_t<_Tp>&>
|
||||
{ };
|
||||
|
||||
// FIXME: needed due to PR c++/67704
|
||||
template<typename _Fn, typename... _Is>
|
||||
struct __indirect_result
|
||||
{ };
|
||||
|
||||
template<typename _Fn, typename... _Is>
|
||||
requires (readable<_Is> && ...)
|
||||
&& invocable<_Fn, iter_reference_t<_Is>...>
|
||||
struct __indirect_result<_Fn, _Is...>
|
||||
: invoke_result<_Fn, iter_reference_t<_Is>...>
|
||||
{ };
|
||||
} // namespace __detail
|
||||
|
||||
template<typename _Tp>
|
||||
using iter_common_reference_t
|
||||
= typename __detail::__iter_common_ref<_Tp>::type;
|
||||
|
||||
/// Requirements for writing a value into an iterator's referenced object.
|
||||
template<typename _Out, typename _Tp>
|
||||
concept writable = requires(_Out&& __o, _Tp&& __t)
|
||||
{
|
||||
*__o = std::forward<_Tp>(__t);
|
||||
*std::forward<_Out>(__o) = std::forward<_Tp>(__t);
|
||||
const_cast<const iter_reference_t<_Out>&&>(*__o)
|
||||
= std::forward<_Tp>(__t);
|
||||
const_cast<const iter_reference_t<_Out>&&>(*std::forward<_Out>(__o))
|
||||
= std::forward<_Tp>(__t);
|
||||
};
|
||||
|
||||
/// Requirements on types that can be incremented with ++.
|
||||
template<typename _Iter>
|
||||
concept weakly_incrementable = default_constructible<_Iter>
|
||||
&& movable<_Iter>
|
||||
&& requires(_Iter __i)
|
||||
{
|
||||
typename iter_difference_t<_Iter>;
|
||||
requires signed_integral<iter_difference_t<_Iter>>;
|
||||
{ ++__i } -> same_as<_Iter&>;
|
||||
__i++;
|
||||
};
|
||||
|
||||
template<typename _Iter>
|
||||
concept incrementable = regular<_Iter> && weakly_incrementable<_Iter>
|
||||
&& requires(_Iter __i) { { __i++ } -> same_as<_Iter>; };
|
||||
|
||||
template<typename _Iter>
|
||||
concept input_or_output_iterator
|
||||
= requires(_Iter __i) { { *__i } -> __detail::__can_reference; }
|
||||
&& weakly_incrementable<_Iter>;
|
||||
|
||||
template<typename _Sent, typename _Iter>
|
||||
concept sentinel_for = semiregular<_Sent>
|
||||
&& input_or_output_iterator<_Iter>
|
||||
&& __detail::__weakly_eq_cmp_with<_Sent, _Iter>;
|
||||
|
||||
template<typename _Sent, typename _Iter>
|
||||
inline constexpr bool disable_sized_sentinel = false;
|
||||
|
||||
template<typename _Sent, typename _Iter>
|
||||
concept sized_sentinel_for = sentinel_for<_Sent, _Iter>
|
||||
&& !disable_sized_sentinel<remove_cv_t<_Sent>, remove_cv_t<_Iter>>
|
||||
&& requires(const _Iter& __i, const _Sent& __s)
|
||||
{
|
||||
{ __s - __i } -> same_as<iter_difference_t<_Iter>>;
|
||||
{ __i - __s } -> same_as<iter_difference_t<_Iter>>;
|
||||
};
|
||||
|
||||
template<typename _Iter>
|
||||
concept input_iterator = input_or_output_iterator<_Iter>
|
||||
&& readable<_Iter>
|
||||
&& requires { typename __detail::__iter_concept<_Iter>; }
|
||||
&& derived_from<__detail::__iter_concept<_Iter>, input_iterator_tag>;
|
||||
|
||||
template<typename _Iter, typename _Tp>
|
||||
concept output_iterator = input_or_output_iterator<_Iter>
|
||||
&& writable<_Iter, _Tp>
|
||||
&& requires(_Iter __i, _Tp&& __t) { *__i++ = std::forward<_Tp>(__t); };
|
||||
|
||||
template<typename _Iter>
|
||||
concept forward_iterator = input_iterator<_Iter>
|
||||
&& derived_from<__detail::__iter_concept<_Iter>, forward_iterator_tag>
|
||||
&& incrementable<_Iter> && sentinel_for<_Iter, _Iter>;
|
||||
|
||||
template<typename _Iter>
|
||||
concept bidirectional_iterator = forward_iterator<_Iter>
|
||||
&& derived_from<__detail::__iter_concept<_Iter>,
|
||||
bidirectional_iterator_tag>
|
||||
&& requires(_Iter __i)
|
||||
{
|
||||
{ --__i } -> same_as<_Iter&>;
|
||||
{ __i-- } -> same_as<_Iter>;
|
||||
};
|
||||
|
||||
template<typename _Iter>
|
||||
concept random_access_iterator = bidirectional_iterator<_Iter>
|
||||
&& derived_from<__detail::__iter_concept<_Iter>,
|
||||
random_access_iterator_tag>
|
||||
&& totally_ordered<_Iter> && sized_sentinel_for<_Iter, _Iter>
|
||||
&& requires(_Iter __i, const _Iter __j,
|
||||
const iter_difference_t<_Iter> __n)
|
||||
{
|
||||
{ __i += __n } -> same_as<_Iter&>;
|
||||
{ __j + __n } -> same_as<_Iter>;
|
||||
{ __n + __j } -> same_as<_Iter>;
|
||||
{ __i -= __n } -> same_as<_Iter&>;
|
||||
{ __j - __n } -> same_as<_Iter>;
|
||||
{ __j[__n] } -> same_as<iter_reference_t<_Iter>>;
|
||||
};
|
||||
|
||||
template<typename _Iter>
|
||||
concept contiguous_iterator = random_access_iterator<_Iter>
|
||||
&& derived_from<__detail::__iter_concept<_Iter>, contiguous_iterator_tag>
|
||||
&& is_lvalue_reference_v<iter_reference_t<_Iter>>
|
||||
&& same_as<iter_value_t<_Iter>, remove_cvref_t<iter_reference_t<_Iter>>>
|
||||
&& requires(const _Iter& __i)
|
||||
{
|
||||
{ std::to_address(__i) }
|
||||
-> same_as<add_pointer_t<iter_reference_t<_Iter>>>;
|
||||
};
|
||||
|
||||
// [indirectcallable], indirect callable requirements
|
||||
|
||||
// [indirectcallable.indirectinvocable], indirect callables
|
||||
|
||||
template<typename _Fn, typename _Iter>
|
||||
concept indirectly_unary_invocable = readable<_Iter>
|
||||
&& copy_constructible<_Fn> && invocable<_Fn&, iter_value_t<_Iter>&>
|
||||
&& invocable<_Fn&, iter_reference_t<_Iter>>
|
||||
&& invocable<_Fn&, iter_common_reference_t<_Iter>>
|
||||
&& common_reference_with<invoke_result_t<_Fn&, iter_value_t<_Iter>&>,
|
||||
invoke_result_t<_Fn&, iter_reference_t<_Iter>>>;
|
||||
|
||||
template<typename _Fn, typename _Iter>
|
||||
concept indirectly_regular_unary_invocable = readable<_Iter>
|
||||
&& copy_constructible<_Fn>
|
||||
&& regular_invocable<_Fn&, iter_value_t<_Iter>&>
|
||||
&& regular_invocable<_Fn&, iter_reference_t<_Iter>>
|
||||
&& regular_invocable<_Fn&, iter_common_reference_t<_Iter>>
|
||||
&& common_reference_with<invoke_result_t<_Fn&, iter_value_t<_Iter>&>,
|
||||
invoke_result_t<_Fn&, iter_reference_t<_Iter>>>;
|
||||
|
||||
template<typename _Fn, typename _Iter>
|
||||
concept indirect_unary_predicate = readable<_Iter>
|
||||
&& copy_constructible<_Fn> && predicate<_Fn&, iter_value_t<_Iter>&>
|
||||
&& predicate<_Fn&, iter_reference_t<_Iter>>
|
||||
&& predicate<_Fn&, iter_common_reference_t<_Iter>>;
|
||||
|
||||
template<typename _Fn, typename _I1, typename _I2 = _I1>
|
||||
concept indirect_relation = readable<_I1> && readable<_I2>
|
||||
&& copy_constructible<_Fn>
|
||||
&& relation<_Fn&, iter_value_t<_I1>&, iter_value_t<_I2>&>
|
||||
&& relation<_Fn&, iter_value_t<_I1>&, iter_reference_t<_I2>>
|
||||
&& relation<_Fn&, iter_reference_t<_I1>, iter_value_t<_I2>&>
|
||||
&& relation<_Fn&, iter_reference_t<_I1>, iter_reference_t<_I2>>
|
||||
&& relation<_Fn&, iter_common_reference_t<_I1>,
|
||||
iter_common_reference_t<_I2>>;
|
||||
|
||||
template<typename _Fn, typename _I1, typename _I2 = _I1>
|
||||
concept indirect_strict_weak_order = readable<_I1> && readable<_I2>
|
||||
&& copy_constructible<_Fn>
|
||||
&& strict_weak_order<_Fn&, iter_value_t<_I1>&, iter_value_t<_I2>&>
|
||||
&& strict_weak_order<_Fn&, iter_value_t<_I1>&, iter_reference_t<_I2>>
|
||||
&& strict_weak_order<_Fn&, iter_reference_t<_I1>, iter_value_t<_I2>&>
|
||||
&& strict_weak_order<_Fn&, iter_reference_t<_I1>, iter_reference_t<_I2>>
|
||||
&& strict_weak_order<_Fn&, iter_common_reference_t<_I1>,
|
||||
iter_common_reference_t<_I2>>;
|
||||
|
||||
template<typename _Fn, typename... _Is>
|
||||
using indirect_result_t = typename
|
||||
__detail::__indirect_result<_Fn, iter_reference_t<_Is>...>::type;
|
||||
|
||||
/// [projected], projected
|
||||
template<readable _Iter, indirectly_regular_unary_invocable<_Iter> _Proj>
|
||||
struct projected
|
||||
{
|
||||
using value_type = remove_cvref_t<indirect_result_t<_Proj&, _Iter>>;
|
||||
indirect_result_t<_Proj&, _Iter> operator*() const; // not defined
|
||||
};
|
||||
|
||||
template<weakly_incrementable _Iter, typename _Proj>
|
||||
struct incrementable_traits<projected<_Iter, _Proj>>
|
||||
{ using difference_type = iter_difference_t<_Iter>; };
|
||||
|
||||
// [alg.req], common algorithm requirements
|
||||
|
||||
/// [alg.req.ind.move], concept `indirectly_movable`
|
||||
|
||||
template<typename _In, typename _Out>
|
||||
concept indirectly_movable = readable<_In>
|
||||
&& writable<_Out, iter_rvalue_reference_t<_In>>;
|
||||
|
||||
template<typename _In, typename _Out>
|
||||
concept indirectly_movable_storable = indirectly_movable<_In, _Out>
|
||||
&& writable<_Out, iter_value_t<_In>> && movable<iter_value_t<_In>>
|
||||
&& constructible_from<iter_value_t<_In>, iter_rvalue_reference_t<_In>>
|
||||
&& assignable_from<iter_value_t<_In>&, iter_rvalue_reference_t<_In>>;
|
||||
|
||||
/// [alg.req.ind.copy], concept `indirectly_copyable`
|
||||
template<typename _In, typename _Out>
|
||||
concept indirectly_copyable = readable<_In>
|
||||
&& writable<_Out, iter_reference_t<_In>>;
|
||||
|
||||
template<typename _In, typename _Out>
|
||||
concept indirectly_copyable_storable = indirectly_copyable<_In, _Out>
|
||||
&& writable<_Out, const iter_value_t<_In>&>
|
||||
&& copyable<iter_value_t<_In>>
|
||||
&& constructible_from<iter_value_t<_In>, iter_reference_t<_In>>
|
||||
&& assignable_from<iter_value_t<_In>&, iter_reference_t<_In>>;
|
||||
|
||||
namespace ranges
|
||||
{
|
||||
namespace __cust_iswap
|
||||
{
|
||||
template<typename _It1, typename _It2>
|
||||
void iter_swap(_It1&, _It2&) = delete;
|
||||
|
||||
template<typename _Tp, typename _Up>
|
||||
concept __adl_iswap
|
||||
= (std::__detail::__class_or_enum<remove_reference_t<_Tp>>
|
||||
|| std::__detail::__class_or_enum<remove_reference_t<_Up>>)
|
||||
&& requires(_Tp&& __t, _Up&& __u) {
|
||||
iter_swap(static_cast<_Tp&&>(__t), static_cast<_Up&&>(__u));
|
||||
};
|
||||
|
||||
template<typename _Xp, typename _Yp>
|
||||
constexpr iter_value_t<remove_reference_t<_Xp>>
|
||||
__iter_exchange_move(_Xp&& __x, _Yp&& __y)
|
||||
noexcept(noexcept(iter_value_t<remove_reference_t<_Xp>>(iter_move(__x)))
|
||||
&& noexcept(*__x = iter_move(__y)))
|
||||
{
|
||||
iter_value_t<remove_reference_t<_Xp>> __old_value(iter_move(__x));
|
||||
*__x = iter_move(__y);
|
||||
return __old_value;
|
||||
}
|
||||
|
||||
struct _IterSwap
|
||||
{
|
||||
private:
|
||||
template<typename _Tp, typename _Up>
|
||||
static constexpr bool
|
||||
_S_noexcept()
|
||||
{
|
||||
if constexpr (__adl_iswap<_Tp, _Up>)
|
||||
return noexcept(iter_swap(std::declval<_Tp>(),
|
||||
std::declval<_Up>()));
|
||||
else if constexpr (readable<_Tp> && readable<_Up>
|
||||
&& swappable_with<iter_reference_t<_Tp>, iter_reference_t<_Up>>)
|
||||
return noexcept(ranges::swap(*std::declval<_Tp>(),
|
||||
*std::declval<_Up>()));
|
||||
else
|
||||
return noexcept(*std::declval<_Tp>()
|
||||
= __iter_exchange_move(std::declval<_Up>(),
|
||||
std::declval<_Tp>()));
|
||||
}
|
||||
|
||||
public:
|
||||
template<typename _Tp, typename _Up>
|
||||
requires __adl_iswap<_Tp, _Up>
|
||||
|| (readable<_Tp> && readable<_Up>
|
||||
&& swappable_with<iter_reference_t<_Tp>, iter_reference_t<_Up>>)
|
||||
|| (indirectly_movable_storable<_Tp, _Up>
|
||||
&& indirectly_movable_storable<_Up, _Tp>)
|
||||
constexpr void
|
||||
operator()(_Tp&& __e1, _Up&& __e2) const
|
||||
noexcept(_S_noexcept<_Tp, _Up>())
|
||||
{
|
||||
if constexpr (__adl_iswap<_Tp, _Up>)
|
||||
iter_swap(static_cast<_Tp&&>(__e1), static_cast<_Up&&>(__e2));
|
||||
else if constexpr (readable<_Tp> && readable<_Up>
|
||||
&& swappable_with<iter_reference_t<_Tp>, iter_reference_t<_Up>>)
|
||||
ranges::swap(*__e1, *__e2);
|
||||
else
|
||||
*__e1 = __iter_exchange_move(__e2, __e1);
|
||||
}
|
||||
};
|
||||
} // namespace __cust_iswap
|
||||
|
||||
inline namespace __cust
|
||||
{
|
||||
inline constexpr __cust_iswap::_IterSwap iter_swap{};
|
||||
} // inline namespace __cust
|
||||
|
||||
} // namespace ranges
|
||||
|
||||
/// [alg.req.ind.swap], concept `indirectly_swappable`
|
||||
template<typename _I1, typename _I2 = _I1>
|
||||
concept indirectly_swappable = readable<_I1> && readable<_I2>
|
||||
&& requires(_I1& __i1, _I2& __i2)
|
||||
{
|
||||
ranges::iter_swap(__i1, __i1);
|
||||
ranges::iter_swap(__i2, __i2);
|
||||
ranges::iter_swap(__i1, __i2);
|
||||
ranges::iter_swap(__i2, __i1);
|
||||
};
|
||||
|
||||
/// [alg.req.ind.cmp], concept `indirectly_comparable`
|
||||
template<typename _I1, typename _I2, typename _Rel, typename _P1 = identity,
|
||||
typename _P2 = identity>
|
||||
concept indirectly_comparable
|
||||
= indirect_relation<_Rel, projected<_I1, _P1>, projected<_I2, _P2>>;
|
||||
|
||||
/// [alg.req.permutable], concept `permutable`
|
||||
template<typename _Iter>
|
||||
concept permutable = forward_iterator<_Iter>
|
||||
&& indirectly_movable_storable<_Iter, _Iter>
|
||||
&& indirectly_swappable<_Iter, _Iter>;
|
||||
|
||||
/// [alg.req.mergeable], concept `mergeable`
|
||||
template<typename _I1, typename _I2, typename _Out,
|
||||
typename _Rel = ranges::less, typename _P1 = identity,
|
||||
typename _P2 = identity>
|
||||
concept mergeable = input_iterator<_I1> && input_iterator<_I2>
|
||||
&& weakly_incrementable<_Out> && indirectly_copyable<_I1, _Out>
|
||||
&& indirectly_copyable<_I2, _Out>
|
||||
&& indirect_strict_weak_order<_Rel, projected<_I1, _P1>,
|
||||
projected<_I2, _P2>>;
|
||||
|
||||
/// [alg.req.sortable], concept `sortable`
|
||||
template<typename _Iter, typename _Rel = ranges::less,
|
||||
typename _Proj = identity>
|
||||
concept sortable = permutable<_Iter>
|
||||
&& indirect_strict_weak_order<_Rel, projected<_Iter, _Proj>>;
|
||||
|
||||
struct unreachable_sentinel_t
|
||||
{
|
||||
template<weakly_incrementable _It>
|
||||
friend constexpr bool
|
||||
operator==(unreachable_sentinel_t, const _It&) noexcept
|
||||
{ return false; }
|
||||
|
||||
#ifndef __cpp_lib_three_way_comparison
|
||||
template<weakly_incrementable _It>
|
||||
friend constexpr bool
|
||||
operator!=(unreachable_sentinel_t, const _It&) noexcept
|
||||
{ return true; }
|
||||
|
||||
template<weakly_incrementable _It>
|
||||
friend constexpr bool
|
||||
operator==(const _It&, unreachable_sentinel_t) noexcept
|
||||
{ return false; }
|
||||
|
||||
template<weakly_incrementable _It>
|
||||
friend constexpr bool
|
||||
operator!=(const _It&, unreachable_sentinel_t) noexcept
|
||||
{ return true; }
|
||||
#endif
|
||||
};
|
||||
|
||||
inline constexpr unreachable_sentinel_t unreachable_sentinel{};
|
||||
|
||||
struct default_sentinel_t { };
|
||||
inline constexpr default_sentinel_t default_sentinel{};
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace std
|
||||
#endif // C++20 library concepts
|
||||
#endif // _ITERATOR_CONCEPTS_H
|
|
@ -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);
|
||||
|
|
|
@ -34,6 +34,8 @@
|
|||
|
||||
#if __cplusplus >= 201103L
|
||||
#include <initializer_list>
|
||||
#include <bits/iterator_concepts.h>
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
@ -342,62 +344,724 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
__adl_begin(_Container& __cont) noexcept(noexcept(begin(__cont)))
|
||||
{ return begin(__cont); }
|
||||
|
||||
template <typename _Container>
|
||||
constexpr auto
|
||||
__adl_end(_Container& __cont) noexcept(noexcept(end(__cont)))
|
||||
{ return end(__cont); }
|
||||
|
||||
template <typename _Container>
|
||||
constexpr auto
|
||||
__adl_cbegin(_Container& __cont) noexcept(noexcept(cbegin(__cont)))
|
||||
{ return cbegin(__cont); }
|
||||
|
||||
template <typename _Container>
|
||||
constexpr auto
|
||||
__adl_cend(_Container& __cont) noexcept(noexcept(cend(__cont)))
|
||||
{ return cend(__cont); }
|
||||
|
||||
template <typename _Container>
|
||||
constexpr auto
|
||||
__adl_rbegin(_Container& __cont) noexcept(noexcept(rbegin(__cont)))
|
||||
{ return rbegin(__cont); }
|
||||
|
||||
template <typename _Container>
|
||||
constexpr auto
|
||||
__adl_rend(_Container& __cont) noexcept(noexcept(rend(__cont)))
|
||||
{ return rend(__cont); }
|
||||
|
||||
template <typename _Container>
|
||||
constexpr auto
|
||||
__adl_crbegin(_Container& __cont) noexcept(noexcept(crbegin(__cont)))
|
||||
{ return crbegin(__cont); }
|
||||
|
||||
template <typename _Container>
|
||||
constexpr auto
|
||||
__adl_crend(_Container& __cont) noexcept(noexcept(crend(__cont)))
|
||||
{ return crend(__cont); }
|
||||
|
||||
template <typename _Container>
|
||||
constexpr auto
|
||||
__adl_data(_Container& __cont) noexcept(noexcept(data(__cont)))
|
||||
{ return data(__cont); }
|
||||
|
||||
template <typename _Container>
|
||||
constexpr auto
|
||||
__adl_cdata(_Container& __cont) noexcept(noexcept(cdata(__cont)))
|
||||
{ return cdata(__cont); }
|
||||
namespace ranges
|
||||
{
|
||||
template<typename>
|
||||
inline constexpr bool disable_sized_range = false;
|
||||
|
||||
template <typename _Container>
|
||||
constexpr auto
|
||||
__adl_size(_Container& __cont) noexcept(noexcept(size(__cont)))
|
||||
{ return size(__cont); }
|
||||
namespace __detail
|
||||
{
|
||||
using __max_diff_type = long long;
|
||||
using __max_size_type = unsigned long long;
|
||||
|
||||
template <typename _Container>
|
||||
constexpr auto
|
||||
__adl_empty(_Container& __cont) noexcept(noexcept(empty(__cont)))
|
||||
{ return empty(__cont); }
|
||||
template<typename _Tp>
|
||||
concept __is_integer_like = integral<_Tp>
|
||||
|| same_as<_Tp, __max_diff_type> || same_as<_Tp, __max_size_type>;
|
||||
|
||||
template<typename _Tp>
|
||||
concept __is_signed_integer_like = signed_integral<_Tp>
|
||||
|| same_as<_Tp, __max_diff_type>;
|
||||
|
||||
template<integral _Tp>
|
||||
constexpr make_unsigned_t<_Tp>
|
||||
__to_unsigned_like(_Tp __t) noexcept
|
||||
{ return __t; }
|
||||
} // namespace __detail
|
||||
|
||||
namespace __cust_access
|
||||
{
|
||||
template<typename _Tp>
|
||||
constexpr decay_t<_Tp>
|
||||
__decay_copy(_Tp&& __t)
|
||||
noexcept(is_nothrow_convertible_v<_Tp, decay_t<_Tp>>)
|
||||
{ return std::forward<_Tp>(__t); }
|
||||
|
||||
template<typename _Tp>
|
||||
concept __member_begin = is_lvalue_reference_v<_Tp>
|
||||
&& requires(_Tp __t)
|
||||
{ { __decay_copy(__t.begin()) } -> input_or_output_iterator; };
|
||||
|
||||
template<typename _Tp> void begin(_Tp&&) = delete;
|
||||
template<typename _Tp> void begin(initializer_list<_Tp>&&) = delete;
|
||||
|
||||
template<typename _Tp>
|
||||
concept __adl_begin = requires(_Tp&& __t)
|
||||
{
|
||||
{ __decay_copy(begin(std::forward<_Tp>(__t))) }
|
||||
-> input_or_output_iterator;
|
||||
};
|
||||
|
||||
template<typename _Tp>
|
||||
concept __complete_type = requires(_Tp* __p) { __p + 1; };
|
||||
|
||||
struct _Begin
|
||||
{
|
||||
private:
|
||||
template<typename _Tp>
|
||||
static constexpr bool
|
||||
_S_noexcept()
|
||||
{
|
||||
if constexpr (__member_begin<_Tp>)
|
||||
return noexcept(__decay_copy(std::declval<_Tp>().begin()));
|
||||
else
|
||||
return noexcept(__decay_copy(begin(std::declval<_Tp>())));
|
||||
}
|
||||
|
||||
public:
|
||||
template<__complete_type _Tp, size_t _Nm>
|
||||
constexpr _Tp*
|
||||
operator()(_Tp (&__e)[_Nm]) const noexcept
|
||||
{ return __e; }
|
||||
|
||||
template<typename _Tp> requires __member_begin<_Tp> || __adl_begin<_Tp>
|
||||
constexpr auto
|
||||
operator()(_Tp&& __e) const noexcept(_S_noexcept<_Tp>())
|
||||
{
|
||||
if constexpr (__member_begin<_Tp>)
|
||||
return __e.begin();
|
||||
else
|
||||
return begin(std::forward<_Tp>(__e));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename _Tp>
|
||||
concept __member_end = is_lvalue_reference_v<_Tp>
|
||||
&& requires(_Tp __t)
|
||||
{
|
||||
{ __decay_copy(__t.end()) }
|
||||
-> sentinel_for<decltype(_Begin{}(__t))>;
|
||||
};
|
||||
|
||||
template<typename _Tp> void end(_Tp&&) = delete;
|
||||
template<typename _Tp> void end(initializer_list<_Tp>&&) = delete;
|
||||
|
||||
template<typename _Tp>
|
||||
concept __adl_end = requires(_Tp&& __t)
|
||||
{
|
||||
{ __decay_copy(end(std::forward<_Tp>(__t))) }
|
||||
-> sentinel_for<decltype(_Begin{}(std::forward<_Tp>(__t)))>;
|
||||
};
|
||||
|
||||
struct _End
|
||||
{
|
||||
private:
|
||||
template<typename _Tp>
|
||||
static constexpr bool
|
||||
_S_noexcept()
|
||||
{
|
||||
if constexpr (__member_end<_Tp>)
|
||||
return noexcept(__decay_copy(std::declval<_Tp>().end()));
|
||||
else
|
||||
return noexcept(__decay_copy(end(std::declval<_Tp>())));
|
||||
}
|
||||
|
||||
public:
|
||||
template<__complete_type _Tp, size_t _Nm>
|
||||
constexpr _Tp*
|
||||
operator()(_Tp (&__e)[_Nm]) const noexcept
|
||||
{ return __e + _Nm; }
|
||||
|
||||
template<typename _Tp> requires __member_end<_Tp> || __adl_end<_Tp>
|
||||
constexpr auto
|
||||
operator()(_Tp&& __e) const noexcept(_S_noexcept<_Tp>())
|
||||
{
|
||||
if constexpr (__member_end<_Tp>)
|
||||
return __e.end();
|
||||
else
|
||||
return end(std::forward<_Tp>(__e));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename _Tp>
|
||||
constexpr decltype(auto)
|
||||
__as_const(_Tp&& __t) noexcept
|
||||
{
|
||||
if constexpr (is_lvalue_reference_v<_Tp>)
|
||||
return static_cast<const remove_reference_t<_Tp>&>(__t);
|
||||
else
|
||||
return static_cast<const _Tp&&>(__t);
|
||||
}
|
||||
|
||||
struct _CBegin
|
||||
{
|
||||
template<typename _Tp>
|
||||
constexpr auto
|
||||
operator()(_Tp&& __e) const
|
||||
noexcept(noexcept(_Begin{}(__cust_access::__as_const((_Tp&&)__e))))
|
||||
requires requires { _Begin{}(__cust_access::__as_const((_Tp&&)__e)); }
|
||||
{
|
||||
return _Begin{}(__cust_access::__as_const(std::forward<_Tp>(__e)));
|
||||
}
|
||||
};
|
||||
|
||||
struct _CEnd
|
||||
{
|
||||
template<typename _Tp>
|
||||
constexpr auto
|
||||
operator()(_Tp&& __e) const
|
||||
noexcept(noexcept(_End{}(__cust_access::__as_const((_Tp&&)__e))))
|
||||
requires requires { _End{}(__cust_access::__as_const((_Tp&&)__e)); }
|
||||
{
|
||||
return _End{}(__cust_access::__as_const(std::forward<_Tp>(__e)));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename _Tp>
|
||||
concept __member_rbegin = is_lvalue_reference_v<_Tp>
|
||||
&& requires(_Tp __t)
|
||||
{ { __decay_copy(__t.rbegin()) } -> input_or_output_iterator; };
|
||||
|
||||
template<typename _Tp> void rbegin(_Tp&&) = delete;
|
||||
|
||||
template<typename _Tp>
|
||||
concept __adl_rbegin = requires(_Tp&& __t)
|
||||
{
|
||||
{ __decay_copy(rbegin(std::forward<_Tp>(__t))) }
|
||||
-> input_or_output_iterator;
|
||||
};
|
||||
|
||||
template<typename _Tp>
|
||||
concept __reversable = requires(_Tp&& __t)
|
||||
{
|
||||
{ _Begin{}(std::forward<_Tp>(__t)) } -> bidirectional_iterator;
|
||||
{ _End{}(std::forward<_Tp>(__t)) }
|
||||
-> same_as<decltype(_Begin{}(std::forward<_Tp>(__t)))>;
|
||||
};
|
||||
|
||||
struct _RBegin
|
||||
{
|
||||
private:
|
||||
template<typename _Tp>
|
||||
static constexpr bool
|
||||
_S_noexcept()
|
||||
{
|
||||
if constexpr (__member_rbegin<_Tp>)
|
||||
return noexcept(__decay_copy(std::declval<_Tp>().rbegin()));
|
||||
else if constexpr (__adl_rbegin<_Tp>)
|
||||
return noexcept(__decay_copy(rbegin(std::declval<_Tp>())));
|
||||
else if constexpr (noexcept(_End{}(std::declval<_Tp>())))
|
||||
{
|
||||
using _It = decltype(_End{}(std::declval<_Tp>()));
|
||||
// std::reverse_iterator copy-initializes its member.
|
||||
return is_nothrow_copy_constructible_v<_It>;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
public:
|
||||
template<typename _Tp>
|
||||
requires __member_rbegin<_Tp> || __adl_rbegin<_Tp> || __reversable<_Tp>
|
||||
constexpr auto
|
||||
operator()(_Tp&& __e) const
|
||||
noexcept(_S_noexcept<_Tp>())
|
||||
{
|
||||
if constexpr (__member_rbegin<_Tp>)
|
||||
return __e.rbegin();
|
||||
else if constexpr (__adl_rbegin<_Tp>)
|
||||
return rbegin(std::forward<_Tp>(__e));
|
||||
else
|
||||
return std::make_reverse_iterator(_End{}(std::forward<_Tp>(__e)));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename _Tp>
|
||||
concept __member_rend = is_lvalue_reference_v<_Tp>
|
||||
&& requires(_Tp __t)
|
||||
{
|
||||
{ __decay_copy(__t.rend()) }
|
||||
-> sentinel_for<decltype(_RBegin{}(__t))>;
|
||||
};
|
||||
|
||||
template<typename _Tp> void rend(_Tp&&) = delete;
|
||||
|
||||
template<typename _Tp>
|
||||
concept __adl_rend = requires(_Tp&& __t)
|
||||
{
|
||||
{ __decay_copy(rend(std::forward<_Tp>(__t))) }
|
||||
-> sentinel_for<decltype(_RBegin{}(std::forward<_Tp>(__t)))>;
|
||||
};
|
||||
|
||||
struct _REnd
|
||||
{
|
||||
private:
|
||||
template<typename _Tp>
|
||||
static constexpr bool
|
||||
_S_noexcept()
|
||||
{
|
||||
if constexpr (__member_rend<_Tp>)
|
||||
return noexcept(__decay_copy(std::declval<_Tp>().rend()));
|
||||
else if constexpr (__adl_rend<_Tp>)
|
||||
return noexcept(__decay_copy(rend(std::declval<_Tp>())));
|
||||
else if constexpr (noexcept(_Begin{}(std::declval<_Tp>())))
|
||||
{
|
||||
using _It = decltype(_Begin{}(std::declval<_Tp>()));
|
||||
// std::reverse_iterator copy-initializes its member.
|
||||
return is_nothrow_copy_constructible_v<_It>;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
public:
|
||||
template<typename _Tp>
|
||||
requires __member_rend<_Tp> || __adl_rend<_Tp> || __reversable<_Tp>
|
||||
constexpr auto
|
||||
operator()(_Tp&& __e) const
|
||||
noexcept(_S_noexcept<_Tp>())
|
||||
{
|
||||
if constexpr (__member_rend<_Tp>)
|
||||
return __e.rend();
|
||||
else if constexpr (__adl_rend<_Tp>)
|
||||
return rend(std::forward<_Tp>(__e));
|
||||
else
|
||||
return std::make_reverse_iterator(_Begin{}(std::forward<_Tp>(__e)));
|
||||
}
|
||||
};
|
||||
|
||||
struct _CRBegin
|
||||
{
|
||||
template<typename _Tp>
|
||||
constexpr auto
|
||||
operator()(_Tp&& __e) const
|
||||
noexcept(noexcept(_RBegin{}(__cust_access::__as_const((_Tp&&)__e))))
|
||||
requires requires { _RBegin{}(__cust_access::__as_const((_Tp&&)__e)); }
|
||||
{
|
||||
return _RBegin{}(__cust_access::__as_const(std::forward<_Tp>(__e)));
|
||||
}
|
||||
};
|
||||
|
||||
struct _CREnd
|
||||
{
|
||||
template<typename _Tp>
|
||||
constexpr auto
|
||||
operator()(_Tp&& __e) const
|
||||
noexcept(noexcept(_REnd{}(__cust_access::__as_const((_Tp&&)__e))))
|
||||
requires requires { _REnd{}(__cust_access::__as_const((_Tp&&)__e)); }
|
||||
{
|
||||
return _REnd{}(__cust_access::__as_const(std::forward<_Tp>(__e)));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename _Tp>
|
||||
concept __member_size = !disable_sized_range<remove_cvref_t<_Tp>>
|
||||
&& requires(_Tp&& __t)
|
||||
{
|
||||
{ __decay_copy(std::forward<_Tp>(__t).size()) }
|
||||
-> __detail::__is_integer_like;
|
||||
};
|
||||
|
||||
template<typename _Tp> void size(_Tp&&) = delete;
|
||||
|
||||
template<typename _Tp>
|
||||
concept __adl_size = !disable_sized_range<remove_cvref_t<_Tp>>
|
||||
&& requires(_Tp&& __t)
|
||||
{
|
||||
{ __decay_copy(size(std::forward<_Tp>(__t))) }
|
||||
-> __detail::__is_integer_like;
|
||||
};
|
||||
|
||||
// FIXME: needed due to PR c++/92268
|
||||
template<forward_iterator _It, sized_sentinel_for<_It> _End>
|
||||
requires requires (_It __it, _End __end)
|
||||
{ { __end - __it } -> __detail::__is_integer_like; }
|
||||
void
|
||||
__subtractable_fwd_iter(_It, _End)
|
||||
{ }
|
||||
|
||||
template<typename _Tp>
|
||||
concept __sizable = requires(_Tp&& __t)
|
||||
{
|
||||
__subtractable_fwd_iter(_Begin{}(std::forward<_Tp>(__t)),
|
||||
_End{}(std::forward<_Tp>(__t)));
|
||||
};
|
||||
|
||||
struct _Size
|
||||
{
|
||||
private:
|
||||
template<typename _Tp>
|
||||
static constexpr bool
|
||||
_S_noexcept()
|
||||
{
|
||||
if constexpr (__member_size<_Tp>)
|
||||
return noexcept(__decay_copy(std::declval<_Tp>().size()));
|
||||
else if constexpr (__adl_size<_Tp>)
|
||||
return noexcept(__decay_copy(size(std::declval<_Tp>())));
|
||||
else if constexpr (__sizable<_Tp>)
|
||||
return noexcept(_End{}(std::declval<_Tp>())
|
||||
- _Begin{}(std::declval<_Tp>()));
|
||||
}
|
||||
|
||||
public:
|
||||
template<__complete_type _Tp, size_t _Nm>
|
||||
constexpr size_t
|
||||
operator()(_Tp (&__e)[_Nm]) const noexcept
|
||||
{ return _Nm; }
|
||||
|
||||
template<typename _Tp>
|
||||
requires __member_size<_Tp> || __adl_size<_Tp> || __sizable<_Tp>
|
||||
constexpr auto
|
||||
operator()(_Tp&& __e) const noexcept(_S_noexcept<_Tp>())
|
||||
{
|
||||
if constexpr (__member_size<_Tp>)
|
||||
return std::forward<_Tp>(__e).size();
|
||||
else if constexpr (__adl_size<_Tp>)
|
||||
return size(std::forward<_Tp>(__e));
|
||||
else if constexpr (__sizable<_Tp>)
|
||||
return __detail::__to_unsigned_like(
|
||||
_End{}(std::forward<_Tp>(__e))
|
||||
- _Begin{}(std::forward<_Tp>(__e)));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename _Tp>
|
||||
concept __member_empty = requires(_Tp&& __t)
|
||||
{ bool(std::forward<_Tp>(__t).empty()); };
|
||||
|
||||
template<typename _Tp>
|
||||
concept __size0_empty = requires(_Tp&& __t)
|
||||
{ _Size{}(std::forward<_Tp>(__t)) == 0; };
|
||||
|
||||
template<typename _Tp>
|
||||
concept __eq_iter_empty = requires(_Tp&& __t)
|
||||
{
|
||||
{ _Begin{}(std::forward<_Tp>(__t)) } -> forward_iterator;
|
||||
bool(_Begin{}(std::forward<_Tp>(__t))
|
||||
== _End{}(std::forward<_Tp>(__t)));
|
||||
};
|
||||
|
||||
struct _Empty
|
||||
{
|
||||
private:
|
||||
template<typename _Tp>
|
||||
static constexpr bool
|
||||
_S_noexcept()
|
||||
{
|
||||
if constexpr (__member_empty<_Tp>)
|
||||
return noexcept(std::declval<_Tp>().empty());
|
||||
else if constexpr (__size0_empty<_Tp>)
|
||||
return noexcept(_Size{}(std::declval<_Tp>()) == 0);
|
||||
else
|
||||
return noexcept(bool(_Begin{}(std::declval<_Tp>())
|
||||
== _End{}(std::declval<_Tp>())));
|
||||
}
|
||||
|
||||
public:
|
||||
template<typename _Tp>
|
||||
requires __member_empty<_Tp> || __size0_empty<_Tp>
|
||||
|| __eq_iter_empty<_Tp>
|
||||
constexpr auto
|
||||
operator()(_Tp&& __e) const noexcept(_S_noexcept<_Tp>())
|
||||
{
|
||||
if constexpr (__member_empty<_Tp>)
|
||||
return bool(std::forward<_Tp>(__e).empty());
|
||||
else if constexpr (__size0_empty<_Tp>)
|
||||
return _Size{}(std::forward<_Tp>(__e)) == 0;
|
||||
else
|
||||
return bool(_Begin{}(std::forward<_Tp>(__e))
|
||||
== _End{}(std::forward<_Tp>(__e)));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename _Tp>
|
||||
concept __pointer_to_object = is_pointer_v<_Tp>
|
||||
&& is_object_v<remove_pointer_t<_Tp>>;
|
||||
|
||||
template<typename _Tp>
|
||||
concept __member_data = is_lvalue_reference_v<_Tp>
|
||||
&& requires(_Tp __t) { { __t.data() } -> __pointer_to_object; };
|
||||
|
||||
template<typename _Tp>
|
||||
concept __begin_data = requires(_Tp&& __t)
|
||||
{ { _Begin{}(std::forward<_Tp>(__t)) } -> contiguous_iterator; };
|
||||
|
||||
struct _Data
|
||||
{
|
||||
private:
|
||||
template<typename _Tp>
|
||||
static constexpr bool
|
||||
_S_noexcept()
|
||||
{
|
||||
if constexpr (__member_data<_Tp>)
|
||||
return noexcept(__decay_copy(std::declval<_Tp>().data()));
|
||||
else
|
||||
return noexcept(_Begin{}(std::declval<_Tp>()));
|
||||
}
|
||||
|
||||
public:
|
||||
template<typename _Tp> requires __member_data<_Tp> || __begin_data<_Tp>
|
||||
constexpr auto
|
||||
operator()(_Tp&& __e) const noexcept(_S_noexcept<_Tp>())
|
||||
{
|
||||
if constexpr (__member_data<_Tp>)
|
||||
return __e.data();
|
||||
else
|
||||
return std::to_address(_Begin{}(std::forward<_Tp>(__e)));
|
||||
}
|
||||
};
|
||||
|
||||
struct _CData
|
||||
{
|
||||
template<typename _Tp>
|
||||
constexpr auto
|
||||
operator()(_Tp&& __e) const
|
||||
noexcept(noexcept(_Data{}(__cust_access::__as_const((_Tp&&)__e))))
|
||||
requires requires { _Data{}(__cust_access::__as_const((_Tp&&)__e)); }
|
||||
{
|
||||
return _Data{}(__cust_access::__as_const(std::forward<_Tp>(__e)));
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace __cust_access
|
||||
|
||||
inline namespace __cust
|
||||
{
|
||||
inline constexpr __cust_access::_Begin begin{};
|
||||
inline constexpr __cust_access::_End end{};
|
||||
inline constexpr __cust_access::_CBegin cbegin{};
|
||||
inline constexpr __cust_access::_CEnd cend{};
|
||||
inline constexpr __cust_access::_RBegin rbegin{};
|
||||
inline constexpr __cust_access::_REnd rend{};
|
||||
inline constexpr __cust_access::_CRBegin crbegin{};
|
||||
inline constexpr __cust_access::_CREnd crend{};
|
||||
inline constexpr __cust_access::_Size size{};
|
||||
inline constexpr __cust_access::_Empty empty{};
|
||||
inline constexpr __cust_access::_Data data{};
|
||||
inline constexpr __cust_access::_CData cdata{};
|
||||
}
|
||||
|
||||
namespace __detail
|
||||
{
|
||||
template<typename _Tp>
|
||||
concept __range_impl = requires(_Tp&& __t) {
|
||||
ranges::begin(std::forward<_Tp>(__t));
|
||||
ranges::end(std::forward<_Tp>(__t));
|
||||
};
|
||||
|
||||
} // namespace __detail
|
||||
|
||||
/// [range.range] The range concept.
|
||||
template<typename _Tp>
|
||||
concept range = __detail::__range_impl<_Tp&>;
|
||||
|
||||
/// [range.sized] The sized_range concept.
|
||||
template<typename _Tp>
|
||||
concept sized_range = range<_Tp>
|
||||
&& requires(_Tp& __t) { ranges::size(__t); };
|
||||
|
||||
// [range.iter.ops] range iterator operations
|
||||
|
||||
template<input_or_output_iterator _It>
|
||||
constexpr void
|
||||
advance(_It& __it, iter_difference_t<_It> __n)
|
||||
{
|
||||
if constexpr (random_access_iterator<_It>)
|
||||
__it += __n;
|
||||
else if constexpr (bidirectional_iterator<_It>)
|
||||
{
|
||||
if (__n > 0)
|
||||
{
|
||||
do
|
||||
{
|
||||
++__it;
|
||||
}
|
||||
while (--__n);
|
||||
}
|
||||
else if (__n < 0)
|
||||
{
|
||||
do
|
||||
{
|
||||
--__it;
|
||||
}
|
||||
while (++__n);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef __cpp_lib_is_constant_evaluated
|
||||
if (std::is_constant_evaluated() && __n < 0)
|
||||
throw "attempt to decrement a non-bidirectional iterator";
|
||||
#endif
|
||||
__glibcxx_assert(__n >= 0);
|
||||
while (__n-- > 0)
|
||||
++__it;
|
||||
}
|
||||
}
|
||||
|
||||
template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
|
||||
constexpr void
|
||||
advance(_It& __it, _Sent __bound)
|
||||
{
|
||||
if constexpr (assignable_from<_It&, _Sent>)
|
||||
__it = std::move(__bound);
|
||||
else if constexpr (sized_sentinel_for<_Sent, _It>)
|
||||
ranges::advance(__it, __bound - __it);
|
||||
else
|
||||
{
|
||||
while (__it != __bound)
|
||||
++__it;
|
||||
}
|
||||
}
|
||||
|
||||
template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
|
||||
constexpr iter_difference_t<_It>
|
||||
advance(_It& __it, iter_difference_t<_It> __n, _Sent __bound)
|
||||
{
|
||||
if constexpr (sized_sentinel_for<_Sent, _It>)
|
||||
{
|
||||
const auto __diff = __bound - __it;
|
||||
#ifdef __cpp_lib_is_constant_evaluated
|
||||
if (std::is_constant_evaluated()
|
||||
&& !(__n == 0 || __diff == 0 || (__n < 0 == __diff < 0)))
|
||||
throw "inconsistent directions for distance and bound";
|
||||
#endif
|
||||
// n and bound must not lead in opposite directions:
|
||||
__glibcxx_assert(__n == 0 || __diff == 0 || (__n < 0 == __diff < 0));
|
||||
const auto __absdiff = __diff < 0 ? -__diff : __diff;
|
||||
const auto __absn = __n < 0 ? -__n : __n;;
|
||||
if (__absn >= __absdiff)
|
||||
{
|
||||
ranges::advance(__it, __bound);
|
||||
return __n - __diff;
|
||||
}
|
||||
else
|
||||
{
|
||||
ranges::advance(__it, __n);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (__it == __bound || __n == 0)
|
||||
return iter_difference_t<_It>(0);
|
||||
else if (__n > 0)
|
||||
{
|
||||
iter_difference_t<_It> __m = 0;
|
||||
do
|
||||
{
|
||||
++__it;
|
||||
++__m;
|
||||
}
|
||||
while (__m != __n && __it != __bound);
|
||||
return __n - __m;
|
||||
}
|
||||
else if constexpr (bidirectional_iterator<_It> && same_as<_It, _Sent>)
|
||||
{
|
||||
iter_difference_t<_It> __m = 0;
|
||||
do
|
||||
{
|
||||
--__it;
|
||||
--__m;
|
||||
}
|
||||
while (__m != __n && __it != __bound);
|
||||
return __n - __m;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef __cpp_lib_is_constant_evaluated
|
||||
if (std::is_constant_evaluated() && __n < 0)
|
||||
throw "attempt to decrement a non-bidirectional iterator";
|
||||
#endif
|
||||
__glibcxx_assert(__n >= 0);
|
||||
return __n;
|
||||
}
|
||||
}
|
||||
|
||||
template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
|
||||
constexpr iter_difference_t<_It>
|
||||
distance(_It __first, _Sent __last)
|
||||
{
|
||||
if constexpr (sized_sentinel_for<_Sent, _It>)
|
||||
return __last - __first;
|
||||
else
|
||||
{
|
||||
iter_difference_t<_It> __n = 0;
|
||||
while (__first != __last)
|
||||
{
|
||||
++__first;
|
||||
++__n;
|
||||
}
|
||||
return __n;
|
||||
}
|
||||
}
|
||||
|
||||
template<range _Range>
|
||||
using iterator_t = decltype(ranges::begin(std::declval<_Range&>()));
|
||||
|
||||
template<range _Range>
|
||||
using range_difference_t = iter_difference_t<iterator_t<_Range>>;
|
||||
|
||||
template<range _Range>
|
||||
constexpr range_difference_t<_Range>
|
||||
distance(_Range&& __r)
|
||||
{
|
||||
if constexpr (sized_range<_Range>)
|
||||
return static_cast<range_difference_t<_Range>>(ranges::size(__r));
|
||||
else
|
||||
return ranges::distance(ranges::begin(__r), ranges::end(__r));
|
||||
}
|
||||
|
||||
template<input_or_output_iterator _It>
|
||||
constexpr _It
|
||||
next(_It __x)
|
||||
{
|
||||
++__x;
|
||||
return __x;
|
||||
}
|
||||
|
||||
template<input_or_output_iterator _It>
|
||||
constexpr _It
|
||||
next(_It __x, iter_difference_t<_It> __n)
|
||||
{
|
||||
ranges::advance(__x, __n);
|
||||
return __x;
|
||||
}
|
||||
|
||||
template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
|
||||
constexpr _It
|
||||
next(_It __x, _Sent __bound)
|
||||
{
|
||||
ranges::advance(__x, __bound);
|
||||
return __x;
|
||||
}
|
||||
|
||||
template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
|
||||
constexpr _It
|
||||
next(_It __x, iter_difference_t<_It> __n, _Sent __bound)
|
||||
{
|
||||
ranges::advance(__x, __n, __bound);
|
||||
return __x;
|
||||
}
|
||||
|
||||
template<bidirectional_iterator _It>
|
||||
constexpr _It
|
||||
prev(_It __x)
|
||||
{
|
||||
--__x;
|
||||
return __x;
|
||||
}
|
||||
|
||||
template<bidirectional_iterator _It>
|
||||
constexpr _It
|
||||
prev(_It __x, iter_difference_t<_It> __n)
|
||||
{
|
||||
ranges::advance(__x, -__n);
|
||||
return __x;
|
||||
}
|
||||
|
||||
template<bidirectional_iterator _It>
|
||||
constexpr _It
|
||||
prev(_It __x, iter_difference_t<_It> __n, _It __bound)
|
||||
{
|
||||
ranges::advance(__x, -__n, __bound);
|
||||
return __x;
|
||||
}
|
||||
|
||||
} // namespace ranges
|
||||
#endif // C++20
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -0,0 +1,142 @@
|
|||
// 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> );
|
|
@ -0,0 +1,143 @@
|
|||
// 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> );
|
36
libstdc++-v3/testsuite/24_iterators/contiguous/concept.cc
Normal file
36
libstdc++-v3/testsuite/24_iterators/contiguous/concept.cc
Normal file
|
@ -0,0 +1,36 @@
|
|||
// 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::*> );
|
34
libstdc++-v3/testsuite/24_iterators/contiguous/tag.cc
Normal file
34
libstdc++-v3/testsuite/24_iterators/contiguous/tag.cc
Normal file
|
@ -0,0 +1,34 @@
|
|||
// 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> );
|
|
@ -0,0 +1,68 @@
|
|||
// 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();
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
// 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();
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
// 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;
|
||||
}
|
204
libstdc++-v3/testsuite/24_iterators/range_operations/advance.cc
Normal file
204
libstdc++-v3/testsuite/24_iterators/range_operations/advance.cc
Normal file
|
@ -0,0 +1,204 @@
|
|||
// 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();
|
||||
}
|
146
libstdc++-v3/testsuite/24_iterators/range_operations/distance.cc
Normal file
146
libstdc++-v3/testsuite/24_iterators/range_operations/distance.cc
Normal file
|
@ -0,0 +1,146 @@
|
|||
// 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();
|
||||
}
|
211
libstdc++-v3/testsuite/24_iterators/range_operations/next.cc
Normal file
211
libstdc++-v3/testsuite/24_iterators/range_operations/next.cc
Normal file
|
@ -0,0 +1,211 @@
|
|||
// 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();
|
||||
}
|
98
libstdc++-v3/testsuite/24_iterators/range_operations/prev.cc
Normal file
98
libstdc++-v3/testsuite/24_iterators/range_operations/prev.cc
Normal file
|
@ -0,0 +1,98 @@
|
|||
// 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());
|
||||
|
|
140
libstdc++-v3/testsuite/std/ranges/access/begin.cc
Normal file
140
libstdc++-v3/testsuite/std/ranges/access/begin.cc
Normal file
|
@ -0,0 +1,140 @@
|
|||
// 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();
|
||||
}
|
91
libstdc++-v3/testsuite/std/ranges/access/cbegin.cc
Normal file
91
libstdc++-v3/testsuite/std/ranges/access/cbegin.cc
Normal file
|
@ -0,0 +1,91 @@
|
|||
// 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();
|
||||
}
|
73
libstdc++-v3/testsuite/std/ranges/access/cdata.cc
Normal file
73
libstdc++-v3/testsuite/std/ranges/access/cdata.cc
Normal file
|
@ -0,0 +1,73 @@
|
|||
// 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();
|
||||
}
|
98
libstdc++-v3/testsuite/std/ranges/access/cend.cc
Normal file
98
libstdc++-v3/testsuite/std/ranges/access/cend.cc
Normal file
|
@ -0,0 +1,98 @@
|
|||
// 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();
|
||||
}
|
73
libstdc++-v3/testsuite/std/ranges/access/crbegin.cc
Normal file
73
libstdc++-v3/testsuite/std/ranges/access/crbegin.cc
Normal file
|
@ -0,0 +1,73 @@
|
|||
// 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();
|
||||
}
|
108
libstdc++-v3/testsuite/std/ranges/access/crend.cc
Normal file
108
libstdc++-v3/testsuite/std/ranges/access/crend.cc
Normal file
|
@ -0,0 +1,108 @@
|
|||
// 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();
|
||||
}
|
78
libstdc++-v3/testsuite/std/ranges/access/data.cc
Normal file
78
libstdc++-v3/testsuite/std/ranges/access/data.cc
Normal file
|
@ -0,0 +1,78 @@
|
|||
// 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();
|
||||
}
|
76
libstdc++-v3/testsuite/std/ranges/access/empty.cc
Normal file
76
libstdc++-v3/testsuite/std/ranges/access/empty.cc
Normal file
|
@ -0,0 +1,76 @@
|
|||
// 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();
|
||||
}
|
145
libstdc++-v3/testsuite/std/ranges/access/end.cc
Normal file
145
libstdc++-v3/testsuite/std/ranges/access/end.cc
Normal file
|
@ -0,0 +1,145 @@
|
|||
// 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();
|
||||
}
|
81
libstdc++-v3/testsuite/std/ranges/access/rbegin.cc
Normal file
81
libstdc++-v3/testsuite/std/ranges/access/rbegin.cc
Normal file
|
@ -0,0 +1,81 @@
|
|||
// 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();
|
||||
}
|
105
libstdc++-v3/testsuite/std/ranges/access/rend.cc
Normal file
105
libstdc++-v3/testsuite/std/ranges/access/rend.cc
Normal file
|
@ -0,0 +1,105 @@
|
|||
// 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();
|
||||
}
|
116
libstdc++-v3/testsuite/std/ranges/access/size.cc
Normal file
116
libstdc++-v3/testsuite/std/ranges/access/size.cc
Normal file
|
@ -0,0 +1,116 @@
|
|||
// 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
|
||||
|
|
Loading…
Add table
Reference in a new issue