//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03, c++11, c++14, c++17 // friend constexpr bool operator==(const CI& y, const sentinel& x); // template // requires sentinel_for, iterator_t>> // friend constexpr bool operator==(const CI& y, const sentinel& x); #include #include #include #include #include #include "test_comparisons.h" #include "test_iterators.h" #include "test_range.h" template using MaybeConstIterator = cpp20_input_iterator>; template class CrossConstComparableSentinel { using Base = std::conditional_t; Base base_; public: CrossConstComparableSentinel() = default; constexpr explicit CrossConstComparableSentinel(Base base) : base_(base) {} friend constexpr bool operator==(const MaybeConstIterator& it, const CrossConstComparableSentinel& se) { return base(it) == se.base_; } friend constexpr bool operator==(const MaybeConstIterator& it, const CrossConstComparableSentinel& se) { return base(it) == se.base_; } }; static_assert(std::sentinel_for, MaybeConstIterator>); static_assert(std::sentinel_for, MaybeConstIterator>); static_assert(std::sentinel_for, MaybeConstIterator>); static_assert(std::sentinel_for, MaybeConstIterator>); struct CrossConstComparableView : std::ranges::view_base { template constexpr explicit CrossConstComparableView(int (&arr)[N]) : b_(arr), e_(arr + N) {} constexpr MaybeConstIterator begin() { return MaybeConstIterator{b_}; } constexpr CrossConstComparableSentinel end() { return CrossConstComparableSentinel{e_}; } constexpr MaybeConstIterator begin() const { return MaybeConstIterator{b_}; } constexpr CrossConstComparableSentinel end() const { return CrossConstComparableSentinel{e_}; } private: int* b_; int* e_; }; static_assert(std::ranges::range); static_assert(std::ranges::range); struct NonCrossConstComparableView : std::ranges::view_base { int* begin(); sentinel_wrapper end(); long* begin() const; sentinel_wrapper end() const; }; static_assert(std::ranges::range); static_assert(std::ranges::range); constexpr bool test() { int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8}; using CrossConstComparableTakeView = std::ranges::take_view; { // Compare CI with sentinel { // Const == true AssertEqualityReturnBool, std::ranges::sentinel_t>(); const CrossConstComparableTakeView tv(CrossConstComparableView{buffer}, 4); assert(testEquality(std::ranges::next(tv.begin(), 4), tv.end(), true)); assert(testEquality(tv.begin(), tv.end(), false)); } { // Const == false AssertEqualityReturnBool, std::ranges::sentinel_t>(); CrossConstComparableTakeView tv(CrossConstComparableView{buffer}, 4); assert(testEquality(std::ranges::next(tv.begin(), 4), tv.end(), true)); assert(testEquality(std::ranges::next(tv.begin(), 1), tv.end(), false)); } } { // Compare CI with sentinel { // Const == true AssertEqualityReturnBool, std::ranges::sentinel_t>(); CrossConstComparableTakeView tv(CrossConstComparableView{buffer}, 4); assert(testEquality(std::ranges::next(std::as_const(tv).begin(), 4), tv.end(), true)); assert(testEquality(std::ranges::next(std::as_const(tv).begin(), 2), tv.end(), false)); } { // Const == false AssertEqualityReturnBool, std::ranges::sentinel_t>(); CrossConstComparableTakeView tv(CrossConstComparableView{buffer}, 4); assert(testEquality(std::ranges::next(tv.begin(), 4), std::as_const(tv).end(), true)); assert(testEquality(std::ranges::next(tv.begin(), 3), std::as_const(tv).end(), false)); } } { // Check invalid comparisons between CI and sentinel using TakeView = std::ranges::take_view; static_assert( !weakly_equality_comparable_with, std::ranges::sentinel_t>); static_assert( !weakly_equality_comparable_with, std::ranges::sentinel_t>); // Those should be valid static_assert( weakly_equality_comparable_with, std::ranges::sentinel_t>); static_assert(weakly_equality_comparable_with, std::ranges::sentinel_t>); } return true; } int main(int, char**) { test(); static_assert(test()); return 0; }