b5b2e3879d
This change replaces the __forwarding_range implementation detail with the ranges::safe_range concept and adds the ranges::enable_safe_range variable template for opt-in in to the concept. It also adjusts the begin/end/rbegin/rend customization point objects to match the new rules for accessing rvalue ranges only when safe to do so. * include/bits/range_access.h (ranges::enable_safe_range): Define. (ranges::begin, ranges::end, ranges::rbegin, ranges::rend): Constrain to only accept types satisfying safe_range and treat argument as an lvalue when calling a member of performing ADL. (ranges::__detail::__range_impl, ranges::__detail::__forwarding_range): Remove. (ranges::range): Adjust definition. (ranges::safe_range): Define. (ranges::iterator_t, ranges::range_difference_t): Reorder definitions to match the synopsis in the working draft. (ranges::disable_sized_range): Remove duplicate definition. * include/experimental/string_view (ranges::enable_safe_range): Add partial specialization for std::experimental::basic_string_view. * include/std/ranges (ranges::viewable_range, ranges::subrange) (ranges::empty_view, ranges::iota_view): Use safe_range. Specialize enable_safe_range. (ranges::safe_iterator_t, ranges::safe_subrange_t): Define. * include/std/span (ranges::enable_safe_range): Add partial specialization for std::span. * include/std/string_view (ranges::enable_safe_range): Likewise for std::basic_string_view. * testsuite/std/ranges/access/begin.cc: Adjust expected results. * testsuite/std/ranges/access/cbegin.cc: Likewise. * testsuite/std/ranges/access/cdata.cc: Likewise. * testsuite/std/ranges/access/cend.cc: Likewise. * testsuite/std/ranges/access/crbegin.cc: Likewise. * testsuite/std/ranges/access/crend.cc: Likewise. * testsuite/std/ranges/access/data.cc: Likewise. * testsuite/std/ranges/access/end.cc: Likewise. * testsuite/std/ranges/access/rbegin.cc: Likewise. * testsuite/std/ranges/access/rend.cc: Likewise. * testsuite/std/ranges/empty_view.cc: Test ranges::begin and ranges::end instead of unqualified calls to begin and end. * testsuite/std/ranges/safe_range.cc: New test. * testsuite/std/ranges/safe_range_types.cc: New test. * testsuite/util/testsuite_iterators.h: Add comment about safe_range. From-SVN: r279135
87 lines
2.3 KiB
C++
87 lines
2.3 KiB
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.
|
|
|
|
// 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 <ranges>
|
|
#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; }
|
|
};
|
|
|
|
// N.B. this is a lie, rbegin on an R1 rvalue will return a dangling pointer.
|
|
template<> constexpr bool std::ranges::enable_safe_range<R1> = true;
|
|
|
|
void
|
|
test01()
|
|
{
|
|
constexpr R1 r;
|
|
static_assert( std::ranges::rbegin(r) == &r.i );
|
|
static_assert( std::ranges::rbegin(std::move(r)) == &r.i );
|
|
}
|
|
|
|
struct R2
|
|
{
|
|
int a[2] = { };
|
|
|
|
constexpr const int* begin() const { return a; }
|
|
constexpr const int* end() const { return a + 2; }
|
|
|
|
friend constexpr const long* begin(const R2&&); // not defined
|
|
friend constexpr const long* end(const R2&&); // not defined
|
|
};
|
|
|
|
// N.B. this is a lie, begin/end on an R2 rvalue will return a dangling pointer.
|
|
template<> constexpr bool std::ranges::enable_safe_range<R2> = true;
|
|
|
|
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();
|
|
}
|