156 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++03, c++11, c++14, c++1710 11// friend constexpr bool operator==(const iterator& x, const iterator& y)12// requires equality_comparable<iterator_t<Base>>;13// friend constexpr bool operator<(const iterator& x, const iterator& y)14// requires random_access_range<Base>;15// friend constexpr bool operator>(const iterator& x, const iterator& y)16// requires random_access_range<Base>;17// friend constexpr bool operator<=(const iterator& x, const iterator& y)18// requires random_access_range<Base>;19// friend constexpr bool operator>=(const iterator& x, const iterator& y)20// requires random_access_range<Base>;21// friend constexpr auto operator<=>(const iterator& x, const iterator& y)22// requires random_access_range<Base> && three_way_comparable<iterator_t<Base>>;23 24#include <compare>25#include <functional>26#include <ranges>27#include <tuple>28 29#include "test_iterators.h"30#include "test_range.h"31 32constexpr void compareOperatorTest(const auto& iter1, const auto& iter2) {33 assert(!(iter1 < iter1));34 assert(iter1 < iter2);35 assert(!(iter2 < iter1));36 37 assert(iter1 <= iter1);38 assert(iter1 <= iter2);39 assert(!(iter2 <= iter1));40 41 assert(!(iter1 > iter1));42 assert(!(iter1 > iter2));43 assert(iter2 > iter1);44 45 assert(iter1 >= iter1);46 assert(!(iter1 >= iter2));47 assert(iter2 >= iter1);48 49 assert(iter1 == iter1);50 assert(!(iter1 == iter2));51 assert(iter2 == iter2);52 53 assert(!(iter1 != iter1));54 assert(iter1 != iter2);55 assert(!(iter2 != iter2));56}57 58constexpr void inequalityOperatorsDoNotExistTest(const auto& iter1, const auto& iter2) {59 using Iter1 = decltype(iter1);60 using Iter2 = decltype(iter2);61 static_assert(!std::is_invocable_v<std::less<>, Iter1, Iter2>);62 static_assert(!std::is_invocable_v<std::less_equal<>, Iter1, Iter2>);63 static_assert(!std::is_invocable_v<std::greater<>, Iter1, Iter2>);64 static_assert(!std::is_invocable_v<std::greater_equal<>, Iter1, Iter2>);65}66 67constexpr bool test() {68 std::tuple<int> ts[] = {{1}, {2}, {3}};69 70 {71 // Test a new-school iterator with operator<=>; the iterator should also have operator<=>.72 using It = three_way_contiguous_iterator<std::tuple<int>*>;73 using Subrange = std::ranges::subrange<It>;74 static_assert(std::three_way_comparable<It>);75 using R = std::ranges::elements_view<Subrange, 0>;76 static_assert(std::three_way_comparable<std::ranges::iterator_t<R>>);77 78 auto ev = Subrange{It{&ts[0]}, It{&ts[0] + 3}} | std::views::elements<0>;79 auto iter1 = ev.begin();80 auto iter2 = iter1 + 1;81 82 compareOperatorTest(iter1, iter2);83 84 assert((iter1 <=> iter2) == std::strong_ordering::less);85 assert((iter1 <=> iter1) == std::strong_ordering::equal);86 assert((iter2 <=> iter1) == std::strong_ordering::greater);87 }88 89 {90 // Test an old-school iterator with no operator<=>; the elements view iterator shouldn't have91 // operator<=> either.92 using It = random_access_iterator<std::tuple<int>*>;93 using Subrange = std::ranges::subrange<It>;94 static_assert(!std::three_way_comparable<It>);95 using R = std::ranges::elements_view<Subrange, 0>;96 static_assert(!std::three_way_comparable<std::ranges::iterator_t<R>>);97 98 auto ev = Subrange{It{&ts[0]}, It{&ts[0] + 3}} | std::views::elements<0>;99 auto iter1 = ev.begin();100 auto iter2 = iter1 + 1;101 102 compareOperatorTest(iter1, iter2);103 }104 105 {106 // non random_access_range107 using It = bidirectional_iterator<std::tuple<int>*>;108 using Subrange = std::ranges::subrange<It>;109 static_assert(!std::ranges::random_access_range<Subrange>);110 using R = std::ranges::elements_view<Subrange, 0>;111 static_assert(!std::three_way_comparable<std::ranges::iterator_t<R>>);112 113 auto ev = Subrange{It{&ts[0]}, It{&ts[0] + 1}} | std::views::elements<0>;114 115 auto it1 = ev.begin();116 auto it2 = ev.end();117 118 assert(it1 == it1);119 assert(!(it1 != it1));120 assert(it2 == it2);121 assert(!(it2 != it2));122 123 assert(it1 != it2);124 125 ++it1;126 assert(it1 == it2);127 128 inequalityOperatorsDoNotExistTest(it1, it2);129 }130 131 {132 // underlying iterator does not support ==133 using Iter = cpp20_input_iterator<std::tuple<int>*>;134 using Sent = sentinel_wrapper<Iter>;135 using Subrange = std::ranges::subrange<Iter, Sent>;136 using R = std::ranges::elements_view<Subrange, 0>;137 static_assert(!std::three_way_comparable<std::ranges::iterator_t<R>>);138 139 auto ev = Subrange{Iter{&ts[0]}, Sent{Iter{&ts[0] + 1}}} | std::views::elements<0>;140 auto it = ev.begin();141 142 using ElemIter = decltype(it);143 static_assert(!weakly_equality_comparable_with<ElemIter, ElemIter>);144 inequalityOperatorsDoNotExistTest(it, it);145 }146 147 return true;148}149 150int main(int, char**) {151 test();152 static_assert(test());153 154 return 0;155}156