Improve `views::drop(_while)` and `views::take(_while)` tests (#3390)

Co-authored-by: Stephan T. Lavavej <stl@nuwen.net>
This commit is contained in:
Jakub Mazurkiewicz 2023-02-14 01:29:04 +01:00 коммит произвёл GitHub
Родитель ade0d6630e
Коммит 580ae14276
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
4 изменённых файлов: 259 добавлений и 1 удалений

Просмотреть файл

@ -289,6 +289,55 @@ constexpr bool test_one(Rng&& rng, Expected&& expected) {
}
}
#if _HAS_CXX23
using ranges::const_iterator_t, ranges::const_sentinel_t, ranges::cbegin, ranges::cend;
// Validate view_interface::cbegin
STATIC_ASSERT(CanMemberCBegin<R> == input_range<V>);
STATIC_ASSERT(same_as<const_iterator_t<R>, const_iterator_t<V>>);
STATIC_ASSERT(CanMemberCBegin<const R&> == (random_access_range<const V> && sized_range<const V>) );
if (forward_range<V>) { // intentionally not if constexpr
const same_as<const_iterator_t<R>> auto i = r.cbegin();
if (!is_empty) {
assert(*i == *cbegin(expected));
}
if constexpr (copyable<V>) {
auto r2 = r;
const same_as<const_iterator_t<R>> auto i2 = r2.cbegin();
if (!is_empty) {
assert(*i2 == *i);
}
}
if constexpr (random_access_range<const V> && sized_range<const V>) {
STATIC_ASSERT(same_as<const_iterator_t<const R>, const_iterator_t<const V>>);
const same_as<const_iterator_t<const R>> auto i3 = as_const(r).cbegin();
if (!is_empty) {
assert(*i3 == *i);
}
}
}
// Validate view_interface::cend
STATIC_ASSERT(CanMemberCEnd<R> == input_range<V>);
STATIC_ASSERT(same_as<const_sentinel_t<R>, const_sentinel_t<V>>);
STATIC_ASSERT(CanMemberCEnd<const R&> == (random_access_range<const V> && sized_range<const V>) );
if (!is_empty) {
same_as<const_sentinel_t<R>> auto i = r.cend();
if constexpr (bidirectional_range<R> && common_range<R>) {
assert(*prev(i) == *prev(cend(expected)));
}
if constexpr (random_access_range<const V> && sized_range<const V>) {
same_as<const_sentinel_t<const R>> auto i2 = as_const(r).cend();
if constexpr (bidirectional_range<const R> && common_range<const R>) {
assert(*prev(i2) == *prev(cend(expected)));
}
}
}
#endif // _HAS_CXX23
// Validate view_interface::data
STATIC_ASSERT(CanMemberData<R> == contiguous_range<V>);
STATIC_ASSERT(CanData<R&> == contiguous_range<V>);

Просмотреть файл

@ -213,6 +213,51 @@ constexpr bool test_one(Rng&& rng, Expected&& expected) {
STATIC_ASSERT(!CanEnd<const R>);
}
#if _HAS_CXX23
using ranges::const_iterator_t, ranges::const_sentinel_t, ranges::cbegin, ranges::cend;
// Validate view_interface::cbegin
STATIC_ASSERT(CanMemberCBegin<R> == ranges::input_range<V>);
if (forward_range<V>) { // intentionally not if constexpr
const same_as<const_iterator_t<R>> auto i = r.cbegin();
if (!is_empty) {
assert(*i == *cbegin(expected));
assert(*r.cbegin() == *cbegin(expected));
}
if constexpr (copyable<V>) {
auto r2 = r;
const same_as<const_iterator_t<R>> auto i2 = r2.cbegin();
if (!is_empty) {
assert(*i2 == *i);
assert(*r2.cbegin() == *i2);
}
}
STATIC_ASSERT(!CanCBegin<const R>);
}
// Validate view_interface::cend
STATIC_ASSERT(CanMemberCEnd<R> == ranges::input_range<V>);
if (!is_empty) {
if constexpr (common_range<V>) {
same_as<const_iterator_t<R>> auto i = r.cend();
if constexpr (bidirectional_range<V>) {
assert(*prev(i) == *prev(cend(expected)));
}
} else {
[[maybe_unused]] same_as<const_sentinel_t<R>> auto s = r.cend();
}
if constexpr (bidirectional_range<V> && common_range<V> && copyable<V>) {
auto r2 = r;
assert(*prev(r2.cend()) == *prev(cend(expected)));
}
STATIC_ASSERT(!CanCEnd<const R>);
}
#endif // _HAS_CXX23
// Validate view_interface::data
STATIC_ASSERT(CanMemberData<R> == contiguous_range<V>);
STATIC_ASSERT(CanData<R&> == contiguous_range<V>);

Просмотреть файл

@ -321,6 +321,86 @@ constexpr bool test_one(Rng&& rng, Expected&& expected) {
}
}
#if _HAS_CXX23
using ranges::const_iterator_t, ranges::const_sentinel_t, ranges::cbegin, ranges::cend;
// Validate view_interface::cbegin
STATIC_ASSERT(CanMemberCBegin<R>);
if constexpr (random_access_range<V> && sized_range<V>) {
STATIC_ASSERT(same_as<const_iterator_t<R>, const_iterator_t<V>>);
} else {
STATIC_ASSERT(same_as<const_iterator_t<R>, const_iterator<counted_iterator<iterator_t<V>>>>);
}
STATIC_ASSERT(CanMemberCBegin<const R&> == input_range<const V>);
if (forward_range<V>) { // intentionally not if constexpr
const same_as<const_iterator_t<R>> auto i = r.cbegin();
if (!is_empty) {
assert(*i == *cbegin(expected));
}
if constexpr (copyable<V>) {
auto r2 = r;
const same_as<const_iterator_t<R>> auto i2 = r2.cbegin();
if (!is_empty) {
assert(*i2 == *i);
}
}
if constexpr (range<const V>) {
if constexpr (random_access_range<const V> && sized_range<const V>) {
STATIC_ASSERT(same_as<const_iterator_t<const R>, const_iterator_t<const V>>);
} else {
STATIC_ASSERT(
same_as<const_iterator_t<const R>, const_iterator<counted_iterator<iterator_t<const V>>>>);
}
const same_as<const_iterator_t<const R>> auto i3 = as_const(r).cbegin();
if (!is_empty) {
assert(*i3 == *i);
}
}
}
// Validate view_interface::cend
STATIC_ASSERT(CanMemberCEnd<R>);
if constexpr (sized_range<V>) {
if constexpr (random_access_range<V>) {
STATIC_ASSERT(same_as<const_sentinel_t<R>, const_iterator_t<V>>);
} else {
STATIC_ASSERT(same_as<const_sentinel_t<R>, default_sentinel_t>);
}
} else {
// Not much we can do here
STATIC_ASSERT(!same_as<const_sentinel_t<R>, const_iterator_t<V>>);
STATIC_ASSERT(!same_as<const_sentinel_t<R>, default_sentinel_t>);
STATIC_ASSERT(is_class_v<const_sentinel_t<R>>);
}
STATIC_ASSERT(CanCEnd<const R&> == range<const V>);
if (!is_empty) {
same_as<const_sentinel_t<R>> auto s = r.cend();
if constexpr (bidirectional_range<R> && common_range<R>) {
assert(*prev(s) == *prev(cend(expected)));
}
if constexpr (range<const V>) {
same_as<const_sentinel_t<const R>> auto sc = as_const(r).cend();
if constexpr (bidirectional_range<const R> && common_range<const R>) {
assert(*prev(sc) == *prev(cend(expected)));
}
if (forward_range<V>) { // intentionally not if constexpr
// Compare with const / non-const iterators
const same_as<const_iterator_t<R>> auto i = r.cbegin();
const same_as<const_iterator_t<const R>> auto ic = as_const(r).cbegin();
assert(s != i);
assert(s != ic);
assert(sc != i);
assert(sc != ic);
}
}
}
#endif // _HAS_CXX23
// Validate view_interface::data
STATIC_ASSERT(CanMemberData<R> == contiguous_range<V>);
STATIC_ASSERT(CanData<R&> == contiguous_range<V>);

Просмотреть файл

@ -239,7 +239,7 @@ constexpr bool test_one(Rng&& rng, Expected&& expected) {
assert(sc == s.base());
assert(sc == sc.base());
} else if constexpr (forward_range<V> && is_lvalue_reference_v<Rng>) {
auto full_range = views::take_while(rng, [](auto const&) { return true; });
auto full_range = views::take_while(rng, [](const auto&) { return true; });
const auto length = 8; // NB: depends on the test data
assert(full_range.end() == next(full_range.begin(), length));
assert(full_range.end() == next(as_const(full_range).begin(), length));
@ -258,6 +258,90 @@ constexpr bool test_one(Rng&& rng, Expected&& expected) {
}
}
#if _HAS_CXX23
using ranges::const_iterator_t, ranges::const_sentinel_t, ranges::cbegin, ranges::cend;
// Validate view_interface::cbegin
STATIC_ASSERT(CanMemberCBegin<R>);
STATIC_ASSERT(CanMemberCBegin<const R> == ranges::range<const R>);
STATIC_ASSERT(indirect_unary_predicate<const Pred, const_iterator_t<const V>>);
if (forward_range<V>) { // intentionally not if constexpr
const same_as<const_iterator_t<R>> auto i = r.cbegin();
if (!is_empty) {
assert(*i == *cbegin(expected));
assert(*r.cbegin() == *cbegin(expected));
}
if constexpr (copyable<V>) {
auto r2 = r;
const same_as<const_iterator_t<R>> auto i2 = r2.cbegin();
if (!is_empty) {
assert(*i2 == *i);
assert(*r2.cbegin() == *i2);
}
}
const same_as<const_iterator_t<const R>> auto ic = as_const(r).cbegin();
if (!is_empty) {
assert(*ic == *cbegin(expected));
assert(*as_const(r).cbegin() == *cbegin(expected));
}
if constexpr (copyable<V>) {
auto rc2 = as_const(r);
const same_as<const_iterator_t<const R>> auto ic2 = rc2.cbegin();
if (!is_empty) {
assert(*ic2 == *ic);
assert(*rc2.cbegin() == *ic2);
}
}
}
// Validate view_interface::cend
STATIC_ASSERT(CanMemberCEnd<R>);
STATIC_ASSERT(CanMemberCEnd<const R> == ranges::range<const R>);
STATIC_ASSERT(indirect_unary_predicate<const Pred, const_iterator_t<const V>>);
STATIC_ASSERT(CanCEnd<const R&> == CanMemberCEnd<const R>);
STATIC_ASSERT(!common_range<R>);
STATIC_ASSERT(!common_range<const R>);
if (!is_empty) {
same_as<const_sentinel_t<R>> auto s = r.cend();
same_as<const_sentinel_t<const R>> auto sc = as_const(r).cend();
if (forward_range<V>) { // intentionally not if constexpr
// Compare with const / non-const iterators
assert(s != r.cbegin());
assert(s != as_const(r).cbegin());
assert(sc != r.cbegin());
assert(sc != as_const(r).cbegin());
// Compare with end of range
if constexpr (common_range<V>) {
assert(s == s.base());
assert(s == sc.base());
assert(sc == s.base());
assert(sc == sc.base());
} else if constexpr (forward_range<V> && is_lvalue_reference_v<Rng>) {
auto full_range = views::take_while(rng, [](const auto&) { return true; });
const auto length = 8; // NB: depends on the test data
assert(full_range.cend() == next(full_range.cbegin(), length));
assert(full_range.cend() == next(as_const(full_range).cbegin(), length));
assert(as_const(full_range).cend() == next(full_range.cbegin(), length));
assert(as_const(full_range).cend() == next(as_const(full_range).cbegin(), length));
}
// Compare with iterator whose predicate evaluates to false
if constexpr (forward_range<V>) {
const auto length = 4; // NB: depends on the test data
assert(s == next(r.cbegin(), length));
assert(s == next(as_const(r).cbegin(), length));
assert(sc == next(r.cbegin(), length));
assert(sc == next(as_const(r).cbegin(), length));
}
}
}
#endif // _HAS_CXX23
// Validate view_interface::data
if constexpr (CanData<R&>) {
const same_as<remove_reference_t<ranges::range_reference_t<V>>*> auto ptr1 = r.data();