On Wed, 26 Nov 2025 at 19:14, Patrick Palka <[email protected]> wrote:
>
> Tested on x86_64-pc-linux-gnu, does this look OK for trunk/15/14?

OK for all three branches, thanks.

>
> -- >8 --
>
> LWG 3946 made const_iterator/sentinel_t get defined directly in terms of
> ranges::cbegin/cend, but I defined it the other way around in an incorrect
> way that made the aliases not consider __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): Adjust
>         test for int[], std::array and std::vector.  Also test
>         std::string.
> ---
>  libstdc++-v3/include/bits/ranges_base.h       | 20 ++++++++----
>  .../24_iterators/const_iterator/1.cc          | 32 +++++++++++++------
>  2 files changed, 36 insertions(+), 16 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..63905e9d63d8 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,11 +65,22 @@ 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> 
> );
> -      static_assert( std::same_as<ranges::range_const_reference_t<Range>,
> -                                std::iter_reference_t<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>> );
> +       }
>
>        static_assert( ranges::input_range<Range> == 
> std::input_iterator<Wrapped> );
>        static_assert( ranges::forward_range<Range> == 
> std::forward_iterator<Wrapped> );
> @@ -138,13 +150,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 +168,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();
> --
> 2.52.0.84.g6ab38b7e9c
>

Reply via email to