https://gcc.gnu.org/g:2d3142c00934c419755c17dd85ecdb0e72f249d1

commit r16-5697-g2d3142c00934c419755c17dd85ecdb0e72f249d1
Author: Patrick Palka <[email protected]>
Date:   Fri Nov 28 15:38:04 2025 -0500

    libstdc++: Correctly implement LWG 3946 changes to const_iterator_t 
[PR122842]
    
    LWG 3946 made const_iterator_t/sentinel_t agree with ranges::cbegin/cend
    by defining the aliases in terms of the CPOs, but I defined it the other
    way around in an incorrect way that made the aliases not consider
    range-ness of const T via __possibly_const_range.  This patch
    reimplements the proposed resolution in a more obviously correct way,
    mirroring the wording.
    
            PR libstdc++/122842
    
    libstdc++-v3/ChangeLog:
    
            * include/bits/ranges_base.h (__access:_CBegin): Define in
            terms of const_iterator directly, not const_iterator_t.
            (__access::_CEnd): Likewise in terms of const_sentinel vs
            const_sentinel_t.
            (const_iterator_t): Move down definition and define in terms
            of ranges::cbegin as per LWG 3946.
            (const_sentinel_t): Likewise in terms of ranges::cend.
            * testsuite/24_iterators/const_iterator/1.cc (test02): Correct
            test for int[], std::array and std::vector.  Also test
            std::string.
    
    Reviewed-by: Tomasz KamiƄski <[email protected]>
    Reviewed-by: Jonathan Wakely <[email protected]>

Diff:
---
 libstdc++-v3/include/bits/ranges_base.h            | 20 +++++++++------
 .../testsuite/24_iterators/const_iterator/1.cc     | 29 ++++++++++++++++------
 2 files changed, 35 insertions(+), 14 deletions(-)

diff --git a/libstdc++-v3/include/bits/ranges_base.h 
b/libstdc++-v3/include/bits/ranges_base.h
index 1c4bf432c8f4..0b8151cd65dd 100644
--- a/libstdc++-v3/include/bits/ranges_base.h
+++ b/libstdc++-v3/include/bits/ranges_base.h
@@ -525,11 +525,7 @@ namespace ranges
     using sentinel_t = decltype(ranges::end(std::declval<_Range&>()));
 
 #if __glibcxx_ranges_as_const // >= C++23
-  template<range _Range>
-    using const_iterator_t = const_iterator<iterator_t<_Range>>;
-
-  template<range _Range>
-    using const_sentinel_t = const_sentinel<sentinel_t<_Range>>;
+  // const_iterator_t and const_sentinel_t defined below.
 
   template<range _Range>
     using range_const_reference_t = iter_const_reference_t<iterator_t<_Range>>;
@@ -683,7 +679,7 @@ namespace ranges
                            
(ranges::begin(__access::__possibly_const_range(__t))); }
        {
          auto& __r = __access::__possibly_const_range(__t);
-         return const_iterator_t<decltype(__r)>(ranges::begin(__r));
+         return 
const_iterator<decltype(ranges::begin(__r))>(ranges::begin(__r));
        }
 #else
       template<typename _Tp>
@@ -711,7 +707,7 @@ namespace ranges
                            
(ranges::end(__access::__possibly_const_range(__t))); }
        {
          auto& __r = __access::__possibly_const_range(__t);
-         return const_sentinel_t<decltype(__r)>(ranges::end(__r));
+         return const_sentinel<decltype(ranges::end(__r))>(ranges::end(__r));
        }
 #else
       template<typename _Tp>
@@ -815,6 +811,16 @@ namespace ranges
     inline constexpr ranges::__access::_CData cdata{};
   }
 
+#if __glibcxx_ranges_as_const // >= C++23
+  // _GLIBCXX_RESOLVE_LIB_DEFECTS
+  // 3946. The definition of const_iterator_t should be reworked
+  template<range _Range>
+    using const_iterator_t = decltype(ranges::cbegin(std::declval<_Range&>()));
+
+  template<range _Range>
+    using const_sentinel_t = decltype(ranges::cend(std::declval<_Range&>()));
+#endif
+
   namespace __detail
   {
     template<typename _Tp>
diff --git a/libstdc++-v3/testsuite/24_iterators/const_iterator/1.cc 
b/libstdc++-v3/testsuite/24_iterators/const_iterator/1.cc
index fe952bfad148..f2bcad4f09c9 100644
--- a/libstdc++-v3/testsuite/24_iterators/const_iterator/1.cc
+++ b/libstdc++-v3/testsuite/24_iterators/const_iterator/1.cc
@@ -42,12 +42,13 @@ test01()
     }
 }
 
-template<class Range, bool Const>
+template<class Range, bool Const, bool Constable = Const>
 void
 test02()
 {
   if constexpr (Const)
     {
+      static_assert(Constable);
       static_assert( ranges::constant_range<Range> );
       static_assert( std::same_as<ranges::const_iterator_t<Range>, 
ranges::iterator_t<Range>> );
       static_assert( std::same_as<ranges::const_sentinel_t<Range>, 
ranges::sentinel_t<Range>> );
@@ -64,9 +65,21 @@ test02()
       static_assert( !ranges::constant_range<Range> );
       using Wrapped = std::basic_const_iterator<ranges::iterator_t<Range>>;
 
-      static_assert( std::same_as<ranges::const_iterator_t<Range>, Wrapped> );
-      if constexpr (ranges::common_range<Range>)
-       static_assert( std::same_as<ranges::const_sentinel_t<Range>, Wrapped> );
+      if constexpr (Constable)
+       {
+         // Verify LWG 3946 changes to const_iterator/sentinel_t (PR122842).
+         static_assert( std::same_as<ranges::const_iterator_t<Range>,
+                                     ranges::iterator_t<const Range>> );
+         static_assert( std::same_as<ranges::const_sentinel_t<Range>,
+                                     ranges::sentinel_t<const Range>> );
+       }
+      else
+       {
+         static_assert( std::same_as<ranges::const_iterator_t<Range>, Wrapped> 
);
+         if constexpr (ranges::common_range<Range>)
+           static_assert( std::same_as<ranges::const_sentinel_t<Range>, 
Wrapped> );
+       }
+
       static_assert( std::same_as<ranges::range_const_reference_t<Range>,
                                 std::iter_reference_t<Wrapped>> );
 
@@ -138,13 +151,14 @@ main()
   test01<std::string_view::iterator, true>();
   test01<std::vector<bool>::const_iterator, true>();
 
-  test02<int[42], false>();
+  test02<int[42], false, true>();
   test02<test_input_range<int>, false>();
   test02<test_forward_range<int>, false>();
   test02<test_bidirectional_range<int>, false>();
   test02<test_random_access_range<int>, false>();
-  test02<std::array<int, 3>, false>();
-  test02<std::vector<bool>, false>();
+  test02<std::array<int, 3>, false, true>();
+  test02<std::vector<bool>, false, true>();
+  test02<std::string, false, true>();
 
   test02<const int[42], true>();
   test02<test_input_range<const int>, true>();
@@ -155,6 +169,7 @@ main()
   test02<const std::array<int, 3>, true>();
   test02<std::string_view, true>();
   test02<const std::vector<bool>, true>();
+  test02<const std::string, true>();
 
   test03();
   test04();

Reply via email to