From 6824949d4e57b6e1b03fa692205187b51f15dc89 Mon Sep 17 00:00:00 2001 From: Mirion <51433180+mirion-dev@users.noreply.github.com> Date: Sun, 5 Apr 2026 15:38:01 +0800 Subject: [PATCH 1/6] Implement LWG-4510 Ambiguity of `std::ranges::advance` and `std::ranges::next` when the difference type is also a sentinel type --- stl/inc/__msvc_iter_core.hpp | 3 ++- .../test.cpp | 22 +++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/stl/inc/__msvc_iter_core.hpp b/stl/inc/__msvc_iter_core.hpp index cfcd369c848..d79d5db7777 100644 --- a/stl/inc/__msvc_iter_core.hpp +++ b/stl/inc/__msvc_iter_core.hpp @@ -406,7 +406,8 @@ concept input_or_output_iterator = requires(_It __i) { } && weakly_incrementable<_It>; _EXPORT_STD template -concept sentinel_for = semiregular<_Se> && input_or_output_iterator<_It> && _Weakly_equality_comparable_with<_Se, _It>; +concept sentinel_for = semiregular<_Se> && !_Integer_like<_Se> && input_or_output_iterator<_It> + && _Weakly_equality_comparable_with<_Se, _It>; _EXPORT_STD template // specializations allowed by N5014 [iterator.concept.sizedsentinel]/3 constexpr bool disable_sized_sentinel_for = false; diff --git a/tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp b/tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp index 52e55ab8a12..4688004fcf6 100644 --- a/tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp +++ b/tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +#include <__msvc_int128.hpp> #include #include #include @@ -1544,6 +1545,27 @@ namespace iterator_concept_sentinel_test { return (unpack_iterator(std::make_index_sequence{}) && ...); } static_assert(unpack_sentinel(std::make_index_sequence{})); + + // Test LWG-4510 + // "Ambiguity of std::ranges::advance and std::ranges::next when the difference type is also a sentinel type" + template + struct iterator { + using difference_type = int; + + iterator& operator++(); + iterator& operator++(int); + iterator& operator*() const; + }; + + struct any { + any(const auto&); + + friend bool operator==(const any&, const any&); + }; + + static_assert(std::input_or_output_iterator>); + static_assert(!std::sentinel_for>); + static_assert(!std::sentinel_for>); } // namespace iterator_concept_sentinel_test namespace iterator_concept_sizedsentinel_test { From 1318f97d0ac8f7bcdde3f124950987ee7781b3d0 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 13 Apr 2026 15:04:54 -0700 Subject: [PATCH 2/6] Extract to `namespace lwg4510`. --- .../test.cpp | 44 ++++++++++--------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp b/tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp index 4688004fcf6..309b5997407 100644 --- a/tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp +++ b/tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp @@ -1545,27 +1545,6 @@ namespace iterator_concept_sentinel_test { return (unpack_iterator(std::make_index_sequence{}) && ...); } static_assert(unpack_sentinel(std::make_index_sequence{})); - - // Test LWG-4510 - // "Ambiguity of std::ranges::advance and std::ranges::next when the difference type is also a sentinel type" - template - struct iterator { - using difference_type = int; - - iterator& operator++(); - iterator& operator++(int); - iterator& operator*() const; - }; - - struct any { - any(const auto&); - - friend bool operator==(const any&, const any&); - }; - - static_assert(std::input_or_output_iterator>); - static_assert(!std::sentinel_for>); - static_assert(!std::sentinel_for>); } // namespace iterator_concept_sentinel_test namespace iterator_concept_sizedsentinel_test { @@ -3699,6 +3678,29 @@ namespace lwg3420 { static_assert(!has_member_value_type>); } // namespace lwg3420 +namespace lwg4510 { + // Test LWG-4510 + // "Ambiguity of std::ranges::advance and std::ranges::next when the difference type is also a sentinel type" + template + struct iterator { + using difference_type = int; + + iterator& operator++(); + iterator& operator++(int); + iterator& operator*() const; + }; + + struct any { + any(const auto&); + + friend bool operator==(const any&, const any&); + }; + + static_assert(std::input_or_output_iterator>); + static_assert(!std::sentinel_for>); + static_assert(!std::sentinel_for>); +} // namespace lwg4510 + namespace vso1121031 { // Validate that indirectly_readable_traits accepts type arguments with both value_type and element_type nested // types if they are consistent. From 3f3a39b2205393a7c281d829d0ac82302f5139e1 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 13 Apr 2026 15:06:13 -0700 Subject: [PATCH 3/6] Avoid quasi-shadowing: `iterator` => `IterType`, `any` => `AnyType`. --- .../test.cpp | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp b/tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp index 309b5997407..6d6de63402b 100644 --- a/tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp +++ b/tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp @@ -3682,23 +3682,23 @@ namespace lwg4510 { // Test LWG-4510 // "Ambiguity of std::ranges::advance and std::ranges::next when the difference type is also a sentinel type" template - struct iterator { + struct IterType { using difference_type = int; - iterator& operator++(); - iterator& operator++(int); - iterator& operator*() const; + IterType& operator++(); + IterType& operator++(int); + IterType& operator*() const; }; - struct any { - any(const auto&); + struct AnyType { + AnyType(const auto&); - friend bool operator==(const any&, const any&); + friend bool operator==(const AnyType&, const AnyType&); }; - static_assert(std::input_or_output_iterator>); - static_assert(!std::sentinel_for>); - static_assert(!std::sentinel_for>); + static_assert(std::input_or_output_iterator>); + static_assert(!std::sentinel_for>); + static_assert(!std::sentinel_for>); } // namespace lwg4510 namespace vso1121031 { From 3c316da1714c3d0fab946439033d79b9de0704ab Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 13 Apr 2026 15:07:02 -0700 Subject: [PATCH 4/6] Avoid abbreviated function templates. --- tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp | 3 ++- 1 file changed, 2 insertions(+), 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 6d6de63402b..fb276448fc4 100644 --- a/tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp +++ b/tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp @@ -3691,7 +3691,8 @@ namespace lwg4510 { }; struct AnyType { - AnyType(const auto&); + template + AnyType(const T&); friend bool operator==(const AnyType&, const AnyType&); }; From c5c410d10e3f2f5dfe2e1373dad28c9293cb0ca3 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 13 Apr 2026 15:09:20 -0700 Subject: [PATCH 5/6] Postincrement should return by value. --- 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 fb276448fc4..5c6b16d5ff7 100644 --- a/tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp +++ b/tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp @@ -3686,7 +3686,7 @@ namespace lwg4510 { using difference_type = int; IterType& operator++(); - IterType& operator++(int); + IterType operator++(int); IterType& operator*() const; }; From 064d419aa14cf76f86baf79293268b5a363d34a2 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 13 Apr 2026 15:14:22 -0700 Subject: [PATCH 6/6] Add a positive test for `sentinel_for`. --- tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp b/tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp index 5c6b16d5ff7..f9f9320da2e 100644 --- a/tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp +++ b/tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp @@ -3688,6 +3688,8 @@ namespace lwg4510 { IterType& operator++(); IterType operator++(int); IterType& operator*() const; + + friend bool operator==(const IterType&, const IterType&); }; struct AnyType { @@ -3698,6 +3700,7 @@ namespace lwg4510 { }; static_assert(std::input_or_output_iterator>); + static_assert(std::sentinel_for, IterType>); static_assert(!std::sentinel_for>); static_assert(!std::sentinel_for>); } // namespace lwg4510