Skip to content

[libc++][NFC] Centralize test for support of == and != in ranges #78481

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <tuple>

#include "test_iterators.h"
#include "test_range.h"

constexpr void compareOperatorTest(const auto& iter1, const auto& iter2) {
assert(!(iter1 < iter1));
Expand Down Expand Up @@ -139,8 +140,7 @@ constexpr bool test() {
auto it = ev.begin();

using ElemIter = decltype(it);
static_assert(!std::invocable<std::equal_to<>, ElemIter, ElemIter>);
static_assert(!std::invocable<std::not_equal_to<>, ElemIter, ElemIter>);
static_assert(!weakly_equality_comparable_with<ElemIter, ElemIter>);
inequalityOperatorsDoNotExistTest(it, it);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <ranges>

#include "../types.h"
#include "test_range.h"

template <bool Const>
struct Iter {
Expand Down Expand Up @@ -63,37 +64,33 @@ struct Range : TupleBufferView {
using R = Range<Sent>;
using CrossComparableR = Range<CrossComparableSent>;

// Test Constraint
template <class I, class S>
concept HasEqual = requires(const I i, const S s) { i == s; };

using std::ranges::elements_view;
using std::ranges::iterator_t;
using std::ranges::sentinel_t;

static_assert(HasEqual<iterator_t<elements_view<R, 0>>, //
sentinel_t<elements_view<R, 0>>>);
static_assert(weakly_equality_comparable_with<iterator_t<elements_view<R, 0>>, //
sentinel_t<elements_view<R, 0>>>);

static_assert(!HasEqual<iterator_t<const elements_view<R, 0>>, //
sentinel_t<elements_view<R, 0>>>);
static_assert(!weakly_equality_comparable_with<iterator_t<const elements_view<R, 0>>, //
sentinel_t<elements_view<R, 0>>>);

static_assert(!HasEqual<iterator_t<elements_view<R, 0>>, //
sentinel_t<const elements_view<R, 0>>>);
static_assert(!weakly_equality_comparable_with<iterator_t<elements_view<R, 0>>, //
sentinel_t<const elements_view<R, 0>>>);

static_assert(HasEqual<iterator_t<const elements_view<R, 0>>, //
sentinel_t<const elements_view<R, 0>>>);
static_assert(weakly_equality_comparable_with<iterator_t<const elements_view<R, 0>>, //
sentinel_t<const elements_view<R, 0>>>);

static_assert(HasEqual<iterator_t<elements_view<R, 0>>, //
sentinel_t<elements_view<R, 0>>>);
static_assert(weakly_equality_comparable_with<iterator_t<elements_view<CrossComparableR, 0>>, //
sentinel_t<elements_view<CrossComparableR, 0>>>);

static_assert(HasEqual<iterator_t<const elements_view<CrossComparableR, 0>>, //
sentinel_t<elements_view<CrossComparableR, 0>>>);
static_assert(weakly_equality_comparable_with<iterator_t<const elements_view<CrossComparableR, 0>>, //
sentinel_t<elements_view<CrossComparableR, 0>>>);

static_assert(HasEqual<iterator_t<elements_view<CrossComparableR, 0>>, //
sentinel_t<const elements_view<CrossComparableR, 0>>>);
static_assert(weakly_equality_comparable_with<iterator_t<elements_view<CrossComparableR, 0>>, //
sentinel_t<const elements_view<CrossComparableR, 0>>>);

static_assert(HasEqual<iterator_t<const elements_view<CrossComparableR, 0>>, //
sentinel_t<const elements_view<CrossComparableR, 0>>>);
static_assert(weakly_equality_comparable_with<iterator_t<const elements_view<CrossComparableR, 0>>, //
sentinel_t<const elements_view<CrossComparableR, 0>>>);

template <class R, bool ConstIter, bool ConstSent>
constexpr void testOne() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@
#include <cassert>
#include <concepts>
#include <utility>

#include "test_iterators.h"
#include "test_macros.h"
#include "../types.h"
#include "test_range.h"

template <class T>
concept has_equal = requires (T const& x, T const& y) { { x == y }; };
#include "../types.h"

template <class Iterator>
constexpr void test() {
Expand Down Expand Up @@ -76,7 +76,7 @@ constexpr bool tests() {
using Sentinel = sentinel_wrapper<Iterator>;
using FilterView = std::ranges::filter_view<minimal_view<Iterator, Sentinel>, AlwaysTrue>;
using FilterIterator = std::ranges::iterator_t<FilterView>;
static_assert(!has_equal<FilterIterator>);
static_assert(!weakly_equality_comparable_with<FilterIterator, FilterIterator>);
}

return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@
#include <type_traits>

#include "../types.h"

template <class Iter, class Sent>
concept EqualityComparable = std::invocable<std::equal_to<>, const Iter&, const Sent&> ;
#include "test_range.h"

using Iterator = random_access_iterator<BufferView<int*>*>;
using ConstIterator = random_access_iterator<const BufferView<int*>*>;
Expand Down Expand Up @@ -53,10 +51,10 @@ struct ConstComparableView : BufferView<BufferView<int*>*> {
constexpr auto end() const { return ConstComparableSentinel<true>(ConstIterator(data_ + size_)); }
};

static_assert(EqualityComparable<std::ranges::iterator_t<ConstComparableView>,
std::ranges::sentinel_t<const ConstComparableView>>);
static_assert(EqualityComparable<std::ranges::iterator_t<const ConstComparableView>,
std::ranges::sentinel_t<ConstComparableView>>);
static_assert(weakly_equality_comparable_with<std::ranges::iterator_t<ConstComparableView>,
std::ranges::sentinel_t<const ConstComparableView>>);
static_assert(weakly_equality_comparable_with<std::ranges::iterator_t<const ConstComparableView>,
std::ranges::sentinel_t<ConstComparableView>>);

constexpr bool test() {
int buffer[4][4] = {{1111, 2222, 3333, 4444}, {555, 666, 777, 888}, {99, 1010, 1111, 1212}, {13, 14, 15, 16}};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,10 @@

#include <concepts>
#include <string_view>

#include "../types.h"

template <class Iter>
concept CanCallEquals = requires(const Iter& i) {
i == i;
i != i;
};
#include "test_range.h"

constexpr bool test() {
// When `View` is a forward range, `inner-iterator` supports both overloads of `operator==`.
Expand Down Expand Up @@ -56,7 +53,7 @@ constexpr bool test() {
auto b = val.begin();
std::same_as<std::default_sentinel_t> decltype(auto) e = val.end();

static_assert(!CanCallEquals<decltype(b)>);
static_assert(!weakly_equality_comparable_with<decltype(b), decltype(b)>);

assert(!(b == std::default_sentinel));
assert(b != std::default_sentinel);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,10 @@

#include <concepts>
#include <string_view>

#include "../types.h"

template <class Iter>
concept CanCallEquals = requires(const Iter& i) {
i == i;
i != i;
};
#include "test_range.h"

constexpr bool test() {
// Forward range supports both overloads of `operator==`.
Expand Down Expand Up @@ -69,7 +66,7 @@ constexpr bool test() {
auto b = v.begin();
std::same_as<std::default_sentinel_t> decltype(auto) e = v.end();

static_assert(!CanCallEquals<decltype(b)>);
static_assert(!weakly_equality_comparable_with<decltype(b), decltype(b)>);

assert(!(b == std::default_sentinel));
assert(b != std::default_sentinel);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,37 +70,33 @@ struct LessThan3 {
constexpr bool operator()(int i) const { return i < 3; }
};

// Test Constraint
template <class I, class S>
concept HasEqual = requires(const I i, const S s) { i == s; };

using std::ranges::iterator_t;
using std::ranges::sentinel_t;
using std::ranges::take_while_view;

static_assert(HasEqual<iterator_t<take_while_view<R, LessThan3>>, //
sentinel_t<take_while_view<R, LessThan3>>>);
static_assert(weakly_equality_comparable_with<iterator_t<take_while_view<R, LessThan3>>, //
sentinel_t<take_while_view<R, LessThan3>>>);

static_assert(!HasEqual<iterator_t<const take_while_view<R, LessThan3>>, //
sentinel_t<take_while_view<R, LessThan3>>>);
static_assert(!weakly_equality_comparable_with<iterator_t<const take_while_view<R, LessThan3>>, //
sentinel_t<take_while_view<R, LessThan3>>>);

static_assert(!HasEqual<iterator_t<take_while_view<R, LessThan3>>, //
sentinel_t<const take_while_view<R, LessThan3>>>);
static_assert(!weakly_equality_comparable_with<iterator_t<take_while_view<R, LessThan3>>, //
sentinel_t<const take_while_view<R, LessThan3>>>);

static_assert(HasEqual<iterator_t<const take_while_view<R, LessThan3>>, //
sentinel_t<const take_while_view<R, LessThan3>>>);
static_assert(weakly_equality_comparable_with<iterator_t<const take_while_view<R, LessThan3>>, //
sentinel_t<const take_while_view<R, LessThan3>>>);

static_assert(HasEqual<iterator_t<take_while_view<R, LessThan3>>, //
sentinel_t<take_while_view<R, LessThan3>>>);
static_assert(weakly_equality_comparable_with<iterator_t<take_while_view<CrossComparableR, LessThan3>>, //
sentinel_t<take_while_view<CrossComparableR, LessThan3>>>);

static_assert(HasEqual<iterator_t<const take_while_view<CrossComparableR, LessThan3>>, //
sentinel_t<take_while_view<CrossComparableR, LessThan3>>>);
static_assert(weakly_equality_comparable_with<iterator_t<const take_while_view<CrossComparableR, LessThan3>>, //
sentinel_t<take_while_view<CrossComparableR, LessThan3>>>);

static_assert(HasEqual<iterator_t<take_while_view<CrossComparableR, LessThan3>>, //
sentinel_t<const take_while_view<CrossComparableR, LessThan3>>>);
static_assert(weakly_equality_comparable_with<iterator_t<take_while_view<CrossComparableR, LessThan3>>, //
sentinel_t<const take_while_view<CrossComparableR, LessThan3>>>);

static_assert(HasEqual<iterator_t<const take_while_view<CrossComparableR, LessThan3>>, //
sentinel_t<const take_while_view<CrossComparableR, LessThan3>>>);
static_assert(weakly_equality_comparable_with<iterator_t<const take_while_view<CrossComparableR, LessThan3>>, //
sentinel_t<const take_while_view<CrossComparableR, LessThan3>>>);

template <class R, bool ConstIter, bool ConstSent>
constexpr void testOne() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

#include "test_comparisons.h"
#include "test_iterators.h"
#include "test_range.h"

template <bool Const>
using MaybeConstIterator = cpp20_input_iterator<std::conditional_t<Const, const int*, int*>>;
Expand Down Expand Up @@ -77,14 +78,6 @@ struct NonCrossConstComparableView : std::ranges::view_base {
static_assert(std::ranges::range<NonCrossConstComparableView>);
static_assert(std::ranges::range<const NonCrossConstComparableView>);

template <class T, class U>
concept weakly_equality_comparable_with = requires(const T& t, const U& u) {
t == u;
t != u;
u == t;
u != t;
};

constexpr bool test() {
int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8};
using CrossConstComparableTakeView = std::ranges::take_view<CrossConstComparableView>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
#include <compare>

#include "test_iterators.h"
#include "test_range.h"

#include "../types.h"

// This is for testing that zip iterator never calls underlying iterator's >, >=, <=, !=.
Expand Down Expand Up @@ -240,7 +242,7 @@ constexpr bool test() {
std::ranges::zip_view r(IterNoEqualView{buffer});
auto it = r.begin();
using Iter = decltype(it);
static_assert(!std::invocable<std::equal_to<>, Iter, Iter>);
static_assert(!weakly_equality_comparable_with<Iter, Iter>);
inequalityOperatorsDoNotExistTest(it, it);
}
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <tuple>

#include "../types.h"
#include "test_range.h"

using Iterator = random_access_iterator<int*>;
using ConstIterator = random_access_iterator<const int*>;
Expand Down Expand Up @@ -54,11 +55,6 @@ struct ConstIncompatibleView : std::ranges::view_base {
sentinel_wrapper<forward_iterator<const int*>> end() const;
};

// clang-format off
template <class Iter, class Sent>
concept EqualComparable = std::invocable<std::equal_to<>, const Iter&, const Sent&>;
// clang-format on

constexpr bool test() {
int buffer1[4] = {1, 2, 3, 4};
int buffer2[5] = {1, 2, 3, 4, 5};
Expand Down Expand Up @@ -95,10 +91,10 @@ constexpr bool test() {
using ConstSentinel = std::ranges::sentinel_t<const decltype(v)>;
static_assert(!std::is_same_v<Sentinel, ConstSentinel>);

static_assert(EqualComparable<Iter, Sentinel>);
static_assert(!EqualComparable<ConstIter, Sentinel>);
static_assert(EqualComparable<Iter, ConstSentinel>);
static_assert(EqualComparable<ConstIter, ConstSentinel>);
static_assert(weakly_equality_comparable_with<Iter, Sentinel>);
static_assert(!weakly_equality_comparable_with<ConstIter, Sentinel>);
static_assert(weakly_equality_comparable_with<Iter, ConstSentinel>);
static_assert(weakly_equality_comparable_with<ConstIter, ConstSentinel>);
}

{
Expand All @@ -120,10 +116,10 @@ constexpr bool test() {
using ConstSentinel = std::ranges::sentinel_t<const decltype(v)>;
static_assert(!std::is_same_v<Sentinel, ConstSentinel>);

static_assert(EqualComparable<Iter, Sentinel>);
static_assert(EqualComparable<ConstIter, Sentinel>);
static_assert(EqualComparable<Iter, ConstSentinel>);
static_assert(EqualComparable<ConstIter, ConstSentinel>);
static_assert(weakly_equality_comparable_with<Iter, Sentinel>);
static_assert(weakly_equality_comparable_with<ConstIter, Sentinel>);
static_assert(weakly_equality_comparable_with<Iter, ConstSentinel>);
static_assert(weakly_equality_comparable_with<ConstIter, ConstSentinel>);
}

{
Expand All @@ -139,10 +135,10 @@ constexpr bool test() {
using ConstSentinel = std::ranges::sentinel_t<const decltype(v)>;
static_assert(!std::is_same_v<Sentinel, ConstSentinel>);

static_assert(EqualComparable<Iter, Sentinel>);
static_assert(!EqualComparable<ConstIter, Sentinel>);
static_assert(!EqualComparable<Iter, ConstSentinel>);
static_assert(EqualComparable<ConstIter, ConstSentinel>);
static_assert(weakly_equality_comparable_with<Iter, Sentinel>);
static_assert(!weakly_equality_comparable_with<ConstIter, Sentinel>);
static_assert(!weakly_equality_comparable_with<Iter, ConstSentinel>);
static_assert(weakly_equality_comparable_with<ConstIter, ConstSentinel>);
}
return true;
}
Expand Down
12 changes: 12 additions & 0 deletions libcxx/test/support/test_range.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@
#define LIBCXX_TEST_SUPPORT_TEST_RANGE_H

#include <concepts>
#include <functional>
#include <iterator>
#include <ranges>
#include <type_traits>

#include "test_iterators.h"

Expand Down Expand Up @@ -94,4 +96,14 @@ concept CanBePiped = requires(View&& view, T&& t) {
{ std::forward<View>(view) | std::forward<T>(t) };
};

// See [concept.equalitycomparable]
template <class T, class U>
concept weakly_equality_comparable_with =
requires(const std::remove_reference_t<T>& t, const std::remove_reference_t<U>& u) {
{ t == u } -> std::same_as<bool>;
{ t != u } -> std::same_as<bool>;
{ u == t } -> std::same_as<bool>;
{ u != t } -> std::same_as<bool>;
};

#endif // LIBCXX_TEST_SUPPORT_TEST_RANGE_H