[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