@@ -2861,6 +2861,32 @@ namespace iter_ops {
28612861 }
28622862 };
28632863
2864+ template <class Element >
2865+ struct pointer_sentinel {
2866+ Element* ptr = nullptr ;
2867+
2868+ pointer_sentinel () = default ;
2869+ constexpr explicit pointer_sentinel (Element* const p) noexcept : ptr{p} {}
2870+
2871+ template <class T >
2872+ [[nodiscard]] constexpr bool operator ==(T* that) const noexcept {
2873+ static_assert (std::same_as<T, Element>);
2874+ return ptr == that;
2875+ }
2876+
2877+ template <class T >
2878+ [[nodiscard]] friend constexpr std::ptrdiff_t operator -(T* x, const pointer_sentinel& y) noexcept {
2879+ static_assert (std::same_as<T, Element>);
2880+ return x - y.ptr ;
2881+ }
2882+
2883+ template <class T >
2884+ [[nodiscard]] friend constexpr std::ptrdiff_t operator -(const pointer_sentinel& y, T* x) noexcept {
2885+ static_assert (std::same_as<T, Element>);
2886+ return y.ptr - x;
2887+ }
2888+ };
2889+
28642890 constexpr bool test_distance () {
28652891 using ranges::distance, ranges::size;
28662892 using std::iter_difference_t , std::same_as;
@@ -2974,6 +3000,26 @@ namespace iter_ops {
29743000 assert (r.t == expected);
29753001 }
29763002
3003+ {
3004+ // Call distance(i, s) with arrays which must be decayed to pointers.
3005+ // (This behavior was regressed by LWG-3392.)
3006+ int some_ints[] = {1 , 2 , 3 };
3007+ assert (distance (some_ints, pointer_sentinel{some_ints + 1 }) == 1 );
3008+ STATIC_ASSERT (noexcept (distance (some_ints, pointer_sentinel{some_ints + 1 })));
3009+ assert (distance (some_ints + 1 , some_ints) == -1 );
3010+ STATIC_ASSERT (noexcept (distance (some_ints + 1 , some_ints)));
3011+ assert (distance (some_ints, some_ints) == 0 );
3012+ STATIC_ASSERT (noexcept (distance (some_ints, some_ints)));
3013+
3014+ const auto & const_ints = some_ints;
3015+ assert (distance (const_ints, pointer_sentinel{const_ints + 1 }) == 1 );
3016+ STATIC_ASSERT (noexcept (distance (const_ints, pointer_sentinel{const_ints + 1 })));
3017+ assert (distance (const_ints + 1 , const_ints) == -1 );
3018+ STATIC_ASSERT (noexcept (distance (const_ints + 1 , const_ints)));
3019+ assert (distance (const_ints, const_ints) == 0 );
3020+ STATIC_ASSERT (noexcept (distance (const_ints, const_ints)));
3021+ }
3022+
29773023 return true ;
29783024 }
29793025 STATIC_ASSERT (test_distance());
0 commit comments