https://gcc.gnu.org/g:7249bc4aacc443faeb054d082d25e5d5cb819df9

commit r17-4250-g7249bc4aacc443faeb054d082d25e5d5cb819df9
Author: Patrick Palka <[email protected]>
Date:   Fri Aug 21 09:20:47 2026 -0400

    libstdc++: Implement LWG 3749 changes to common_iterator
    
    A couple of backwards compatibility notes:
    
    Since iterator_traits is an empty type the new base class must depend on
    both the iterator and sentinel types so that two iterator_traits<_It, 
_Sent1>
    and iterator_traits<_It, _Sent2> subobjects continue to be potentially
    overlapping for _Sent1 != _Sent2.
    
    And it must be a public base so that iterator_traits<common_iterator>
    continues to be an aggregate type.
    
    libstdc++-v3/ChangeLog:
    
            * include/bits/stl_iterator.h
            (__detail::__common_iterator_iter_cat): New.
            (iterator_traits<common_iterator>): Use it to conditionally
            define iterator_category as per LWG 3749.
            * testsuite/24_iterators/common_iterator/1.cc (test_lwg3749):
            New test.
    
    Reviewed-by: Jonathan Wakely <[email protected]>

Diff:
---
 libstdc++-v3/include/bits/stl_iterator.h           | 37 +++++++++++++++-------
 .../testsuite/24_iterators/common_iterator/1.cc    | 23 ++++++++++++++
 2 files changed, 49 insertions(+), 11 deletions(-)

diff --git a/libstdc++-v3/include/bits/stl_iterator.h 
b/libstdc++-v3/include/bits/stl_iterator.h
index f5f2abbb8b6b..bcc22c50de57 100644
--- a/libstdc++-v3/include/bits/stl_iterator.h
+++ b/libstdc++-v3/include/bits/stl_iterator.h
@@ -2297,8 +2297,33 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       using difference_type = iter_difference_t<_It>;
     };
 
+  namespace __detail
+  {
+    template<typename _It, typename _Sent>
+      struct __common_iterator_iter_cat
+      { };
+
+    template<typename _It, typename _Sent>
+      requires integral<iter_difference_t<_It>>
+      struct __common_iterator_iter_cat<_It, _Sent>
+      {
+       static auto
+       _S_iter_cat()
+       {
+         if constexpr (requires { requires derived_from<__iter_category_t<_It>,
+                                                        forward_iterator_tag>; 
})
+           return forward_iterator_tag{};
+         else
+           return input_iterator_tag{};
+       }
+
+       using iterator_category = decltype(_S_iter_cat());
+      };
+  } // namespace __detail
+
   template<input_iterator _It, typename _Sent>
     struct iterator_traits<common_iterator<_It, _Sent>>
+    : __detail::__common_iterator_iter_cat<_It, _Sent>
     {
     private:
       template<typename _Iter>
@@ -2315,21 +2340,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
          using type = decltype(std::declval<const _CIter&>().operator->());
        };
 
-      static auto
-      _S_iter_cat()
-      {
-       if constexpr (requires { requires derived_from<__iter_category_t<_It>,
-                                                      forward_iterator_tag>; })
-         return forward_iterator_tag{};
-       else
-         return input_iterator_tag{};
-      }
-
     public:
       using iterator_concept = __conditional_t<forward_iterator<_It>,
                                               forward_iterator_tag,
                                               input_iterator_tag>;
-      using iterator_category = decltype(_S_iter_cat());
+      // iterator_category defined in base __common_iterator_iter_cat
       using value_type = iter_value_t<_It>;
       using difference_type = iter_difference_t<_It>;
       using pointer = typename __ptr<_It>::type;
diff --git a/libstdc++-v3/testsuite/24_iterators/common_iterator/1.cc 
b/libstdc++-v3/testsuite/24_iterators/common_iterator/1.cc
index 77ee33f8ee94..1f830766f912 100644
--- a/libstdc++-v3/testsuite/24_iterators/common_iterator/1.cc
+++ b/libstdc++-v3/testsuite/24_iterators/common_iterator/1.cc
@@ -18,6 +18,7 @@
 // { dg-do run { target c++20 } }
 
 #include <iterator>
+#include <ranges>
 #include <testsuite_hooks.h>
 
 void
@@ -193,6 +194,28 @@ test_pr103992()
 
 static_assert( test_pr103992() );
 
+template<typename Iter>
+concept has_iter_cat = requires { typename 
std::iterator_traits<Iter>::iterator_category; };
+
+constexpr bool
+test_lwg3749()
+{
+  // LWG 3749 - common_iterator should handle integer-class difference types
+#if __SIZEOF_INT128__
+  auto v = std::views::iota(__int128(0));
+#else
+  auto v = std::views::iota(0ll);
+#endif
+
+  using Iter = decltype(v.begin());
+  static_assert( ! std::integral<std::iter_difference_t<Iter>> );
+  static_assert( ! has_iter_cat<std::common_iterator<Iter, 
std::unreachable_sentinel_t>> );
+
+  return true;
+}
+
+static_assert( test_lwg3749() );
+
 int
 main()
 {

Reply via email to