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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 // UNSUPPORTED: c++03, c++11, c++14, c++17 10 // UNSUPPORTED: libcpp-has-no-incomplete-ranges 11 12 // template<class I, sentinel_for<I> S> 13 // requires (!sized_sentinel_for<S, I>) 14 // constexpr iter_difference_t<I> ranges::distance(I first, S last); 15 // 16 // template<class I, sized_sentinel_for<decay_t<I>> S> 17 // constexpr iter_difference_t<I> ranges::distance(const I& first, S last); 18 19 #include <iterator> 20 #include <cassert> 21 22 #include "test_iterators.h" 23 24 template<class It> 25 struct EvilSentinel { 26 It p_; 27 friend constexpr bool operator==(EvilSentinel s, It p) { return s.p_ == p; } 28 friend constexpr auto operator-(EvilSentinel s, It p) { return s.p_ - p; } 29 friend constexpr auto operator-(It p, EvilSentinel s) { return p - s.p_; } 30 friend constexpr void operator-(EvilSentinel s, int(&)[3]) = delete; 31 friend constexpr void operator-(EvilSentinel s, int(&&)[3]) = delete; 32 friend constexpr void operator-(EvilSentinel s, const int(&)[3]) = delete; 33 friend constexpr void operator-(EvilSentinel s, const int(&&)[3]) = delete; 34 }; 35 static_assert( std::sized_sentinel_for<EvilSentinel<int*>, int*>); 36 static_assert(!std::sized_sentinel_for<EvilSentinel<int*>, const int*>); 37 static_assert( std::sized_sentinel_for<EvilSentinel<const int*>, int*>); 38 static_assert( std::sized_sentinel_for<EvilSentinel<const int*>, const int*>); 39 40 constexpr bool test() { 41 { 42 int a[] = {1, 2, 3}; 43 assert(std::ranges::distance(a, a + 3) == 3); 44 assert(std::ranges::distance(a, a) == 0); 45 assert(std::ranges::distance(a + 3, a) == -3); 46 } 47 { 48 int a[] = {1, 2, 3}; 49 assert(std::ranges::distance(a, EvilSentinel<int*>{a+3}) == 3); 50 assert(std::ranges::distance(a, EvilSentinel<int*>{a}) == 0); 51 assert(std::ranges::distance(a+3, EvilSentinel<int*>{a}) == -3); 52 assert(std::ranges::distance(std::move(a), EvilSentinel<int*>{a+3}) == 3); 53 } 54 { 55 const int a[] = {1, 2, 3}; 56 assert(std::ranges::distance(a, EvilSentinel<const int*>{a+3}) == 3); 57 assert(std::ranges::distance(a, EvilSentinel<const int*>{a}) == 0); 58 assert(std::ranges::distance(a+3, EvilSentinel<const int*>{a}) == -3); 59 assert(std::ranges::distance(std::move(a), EvilSentinel<const int*>{a+3}) == 3); 60 static_assert(!std::is_invocable_v<decltype(std::ranges::distance), const int(&)[3], EvilSentinel<int*>>); 61 static_assert(!std::is_invocable_v<decltype(std::ranges::distance), const int(&&)[3], EvilSentinel<int*>>); 62 } 63 64 return true; 65 } 66 67 int main(int, char**) { 68 test(); 69 static_assert(test()); 70 71 return 0; 72 } 73