[libc++] Fix __simple_view concept in std::ranges

Differential Revision: https://reviews.llvm.org/D116808
This commit is contained in:
Hui Xie 2022-01-14 12:54:02 -05:00 committed by Louis Dionne
parent 02455bea6b
commit 597b90ebac
5 changed files with 101 additions and 3 deletions

View File

@ -83,11 +83,11 @@ namespace ranges {
movable<_Tp> &&
enable_view<_Tp>;
template<class _Range>
template <class _Range>
concept __simple_view =
view<_Range> && range<const _Range> &&
same_as<iterator_t<_Range>, iterator_t<const _Range>> &&
same_as<sentinel_t<_Range>, iterator_t<const _Range>>;
same_as<sentinel_t<_Range>, sentinel_t<const _Range>>;
// [range.refinements], other range refinements
template <class _Rp, class _Tp>

View File

@ -39,7 +39,14 @@ struct DifferentSentinel : std::ranges::view_base {
sentinel_wrapper<int*> end() const;
};
struct WrongConstSentinel : std::ranges::view_base {
int *begin() const;
sentinel_wrapper<int*> end();
sentinel_wrapper<const int*> end() const;
};
static_assert( std::ranges::__simple_view<SimpleView>);
static_assert(!std::ranges::__simple_view<WrongConstView>);
static_assert(!std::ranges::__simple_view<NoConstView>);
static_assert(!std::ranges::__simple_view<DifferentSentinel>);
static_assert( std::ranges::__simple_view<DifferentSentinel>);
static_assert(!std::ranges::__simple_view<WrongConstSentinel>);

View File

@ -19,11 +19,32 @@
#include <ranges>
#include "test_macros.h"
#include "test_iterators.h"
#include "types.h"
template<class T>
concept BeginInvocable = requires(std::ranges::drop_view<T> t) { t.begin(); };
template <bool IsSimple>
struct MaybeSimpleView : std::ranges::view_base {
int* num_of_non_const_begin_calls;
int* num_of_const_begin_calls;
constexpr int* begin() {
++(*num_of_non_const_begin_calls);
return nullptr;
}
constexpr std::conditional_t<IsSimple, int*, const int*> begin() const {
++(*num_of_const_begin_calls);
return nullptr;
}
constexpr int* end() const { return nullptr; }
constexpr size_t size() const { return 0; }
};
using SimpleView = MaybeSimpleView<true>;
using NonSimpleView = MaybeSimpleView<false>;
constexpr bool test() {
// random_access_range<const V> && sized_range<const V>
std::ranges::drop_view dropView1(MoveOnlyView(), 4);
@ -62,6 +83,36 @@ constexpr bool test() {
static_assert(!BeginInvocable<const ForwardView>);
{
static_assert(std::ranges::random_access_range<const SimpleView>);
static_assert(std::ranges::sized_range<const SimpleView>);
LIBCPP_STATIC_ASSERT(std::ranges::__simple_view<SimpleView>);
int non_const_calls = 0;
int const_calls = 0;
std::ranges::drop_view dropView(SimpleView{{}, &non_const_calls, &const_calls}, 4);
assert(dropView.begin() == nullptr);
assert(non_const_calls == 0);
assert(const_calls == 1);
assert(std::as_const(dropView).begin() == nullptr);
assert(non_const_calls == 0);
assert(const_calls == 2);
}
{
static_assert(std::ranges::random_access_range<const NonSimpleView>);
static_assert(std::ranges::sized_range<const NonSimpleView>);
LIBCPP_STATIC_ASSERT(!std::ranges::__simple_view<NonSimpleView>);
int non_const_calls = 0;
int const_calls = 0;
std::ranges::drop_view dropView(NonSimpleView{{}, &non_const_calls, &const_calls}, 4);
assert(dropView.begin() == nullptr);
assert(non_const_calls == 1);
assert(const_calls == 0);
assert(std::as_const(dropView).begin() == nullptr);
assert(non_const_calls == 1);
assert(const_calls == 1);
}
return true;
}

View File

@ -19,6 +19,17 @@
#include "test_macros.h"
#include "types.h"
struct NonSimpleParentView : std::ranges::view_base {
ChildView* begin() { return nullptr; }
const ChildView* begin() const;
const ChildView* end() const;
};
struct SimpleParentView : std::ranges::view_base {
const ChildView* begin() const;
const ChildView* end() const;
};
constexpr bool test() {
int buffer[4][4] = {{1111, 2222, 3333, 4444}, {555, 666, 777, 888}, {99, 1010, 1111, 1212}, {13, 14, 15, 16}};
@ -86,6 +97,20 @@ constexpr bool test() {
assert(*jv.begin() == 1111);
}
// !simple-view<V>
{
std::ranges::join_view<NonSimpleParentView> jv;
static_assert(!std::same_as<decltype(jv.begin()),
decltype(std::as_const(jv).begin())>);
}
// simple-view<V> && is_reference_v<range_reference_t<V>>;
{
std::ranges::join_view<SimpleParentView> jv;
static_assert(std::same_as<decltype(jv.begin()),
decltype(std::as_const(jv).begin())>);
}
return true;
}

View File

@ -21,6 +21,14 @@
#include "test_range.h"
#include "types.h"
struct NonCommonSimpleView : std::ranges::view_base {
int* begin() const;
sentinel_wrapper<int*> end() const;
size_t size() { return 0; } // deliberately non-const
};
static_assert(std::ranges::sized_range<NonCommonSimpleView>);
static_assert(!std::ranges::sized_range<const NonCommonSimpleView>);
constexpr bool test() {
int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8};
@ -63,6 +71,13 @@ constexpr bool test() {
ASSERT_SAME_TYPE(decltype(tv.begin()), std::counted_iterator<int*>);
}
// __simple_view<V> && sized_range<V> && !size_range<!V>
{
std::ranges::take_view<NonCommonSimpleView> tv{};
ASSERT_SAME_TYPE(decltype(tv.begin()), std::counted_iterator<int*>);
ASSERT_SAME_TYPE(decltype(std::as_const(tv).begin()), std::counted_iterator<int*>);
}
return true;
}