[PATCH] libstdc++: Implement LWG 3749 changes to common_iterator

Jonathan Wakely jwakely@redhat.com
Fri Aug 21 13:53:24 GMT 2026


On Fri, 21 Aug 2026 at 14:22, Patrick Palka <ppalka@redhat.com> wrote:
>
> Tested on x86_64-pc-linux-gnu, does this look OK for trunk and later
> backports?

OK for all, thanks

>
> -- >8 --
>
> 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.
> ---
>  libstdc++-v3/include/bits/stl_iterator.h      | 37 +++++++++++++------
>  .../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()
>  {
> --
> 2.55.0.618.g1a3e64c6c4
>



More information about the Libstdc++ mailing list