From 3d3e8a8d50a4cd63a41ead52557f1a0b310b27f6 Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Wed, 3 Aug 2022 09:19:53 -0700 Subject: [PATCH 1/4] `ranges::distance` needs to better emulate the two overload presentation of LWG-3664 By constraining itself with the union of the constraints of those two overloads. Test coverage is incoming in the LLVM update, against which I've verified the fix. --- stl/inc/xutility | 3 +++ 1 file changed, 3 insertions(+) diff --git a/stl/inc/xutility b/stl/inc/xutility index 30bcfb7b623..ac8a9fa1824 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -2507,9 +2507,12 @@ namespace ranges { public: using _Not_quite_object::_Not_quite_object; + // clang-format off template > _Se> + requires sized_sentinel_for<_Se, decay_t<_It>> || constructible_from, _It> _NODISCARD constexpr iter_difference_t> operator()(_It&& _Raw_first, _Se _Last) const noexcept(_Nothrow_dist<_It, _Se>) /* strengthened */ { + // clang-format on if constexpr (sized_sentinel_for<_Se, decay_t<_It>>) { return _Last - static_cast&>(_Raw_first); // Per LWG-3664 } else { From dc5368af65660dad7bb50104ee197daeff2a8867 Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Wed, 3 Aug 2022 11:17:32 -0700 Subject: [PATCH 2/4] Split the implementation per Nicole's request --- stl/inc/xutility | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/stl/inc/xutility b/stl/inc/xutility index ac8a9fa1824..6aa7ea73cbd 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -2507,19 +2507,19 @@ namespace ranges { public: using _Not_quite_object::_Not_quite_object; - // clang-format off - template > _Se> - requires sized_sentinel_for<_Se, decay_t<_It>> || constructible_from, _It> - _NODISCARD constexpr iter_difference_t> operator()(_It&& _Raw_first, _Se _Last) const - noexcept(_Nothrow_dist<_It, _Se>) /* strengthened */ { - // clang-format on - if constexpr (sized_sentinel_for<_Se, decay_t<_It>>) { - return _Last - static_cast&>(_Raw_first); // Per LWG-3664 - } else { - auto _First = _STD forward<_It>(_Raw_first); - _Adl_verify_range(_First, _Last); - return _Distance_unchecked(_Get_unwrapped(_STD move(_First)), _Get_unwrapped(_STD move(_Last))); - } + template _Se> + requires(!sized_sentinel_for<_Se, _It>) + _NODISCARD constexpr iter_difference_t<_It> operator()(_It _First, _Se _Last) const + noexcept(noexcept(_Distance_unchecked( + _Get_unwrapped(_STD move(_First)), _Get_unwrapped(_STD move(_Last))))) /* strengthened */ { + _Adl_verify_range(_First, _Last); + return _Distance_unchecked(_Get_unwrapped(_STD move(_First)), _Get_unwrapped(_STD move(_Last))); + } + + template > _Se> + _NODISCARD constexpr iter_difference_t> operator()(_It&& _First, const _Se _Last) const + noexcept(noexcept(_Last - static_cast&>(_First))) /* strengthened */ { // Per LWG-3664 + return _Last - static_cast&>(_First); } template @@ -2533,13 +2533,6 @@ namespace ranges { } private: - template - static constexpr bool _Nothrow_dist = false; - - template > _Se> - static constexpr bool _Nothrow_dist<_It, _Se> = noexcept( - _STD declval<_Se&>() - _STD declval&>()); - template _NODISCARD static constexpr iter_difference_t<_It> _Distance_unchecked(_It _First, const _Se _Last) noexcept( noexcept(++_First != _Last)) { From 9213ec0fd986ed6a11d87113aad827a4edbbbb3b Mon Sep 17 00:00:00 2001 From: Nicole Mazzuca Date: Mon, 22 Aug 2022 14:07:03 -0700 Subject: [PATCH 3/4] fix tests --- tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp b/tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp index 0a9e743930b..7fe5dde16d2 100644 --- a/tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp +++ b/tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp @@ -2959,7 +2959,7 @@ namespace iter_ops { trace t{}; I first{t}; same_as> auto const result = distance(move(first), default_sentinel); - STATIC_ASSERT(!noexcept(distance(move(first), default_sentinel))); // No conditional noexcept + STATIC_ASSERT(noexcept(distance(move(first), default_sentinel))); // No conditional noexcept assert(result == sentinel_position); assert((t == trace{.compares_ = sentinel_position + 1, .increments_ = sentinel_position})); } From 56e45097c9cc13e06f47ccf4fcee0f47c586c665 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 25 Aug 2022 18:15:10 -0700 Subject: [PATCH 4/4] Update comments. --- stl/inc/xutility | 4 ++-- tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/stl/inc/xutility b/stl/inc/xutility index 0b36fed45df..5c470ceec76 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -2579,8 +2579,8 @@ namespace ranges { template _Se> requires(!sized_sentinel_for<_Se, _It>) _NODISCARD constexpr iter_difference_t<_It> operator()(_It _First, _Se _Last) const - noexcept(noexcept(_Distance_unchecked( - _Get_unwrapped(_STD move(_First)), _Get_unwrapped(_STD move(_Last))))) /* strengthened */ { + noexcept(noexcept(_Distance_unchecked(_Get_unwrapped(_STD move(_First)), + _Get_unwrapped(_STD move(_Last))))) /* strengthened */ { // Per LWG-3664 _Adl_verify_range(_First, _Last); return _Distance_unchecked(_Get_unwrapped(_STD move(_First)), _Get_unwrapped(_STD move(_Last))); } diff --git a/tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp b/tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp index 7fe5dde16d2..563a0229e36 100644 --- a/tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp +++ b/tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp @@ -2959,7 +2959,7 @@ namespace iter_ops { trace t{}; I first{t}; same_as> auto const result = distance(move(first), default_sentinel); - STATIC_ASSERT(noexcept(distance(move(first), default_sentinel))); // No conditional noexcept + STATIC_ASSERT(noexcept(distance(move(first), default_sentinel))); assert(result == sentinel_position); assert((t == trace{.compares_ = sentinel_position + 1, .increments_ = sentinel_position})); }