On Wed, 12 Mar 2025, Patrick Palka wrote:

> Tested on x86_64-pc-linux-gnu, does this look OK for trunk/14 and
> perhaps 13?
> 
> N.B. the use of a constrained auto instead of a separate static_assert
> in the testcase is unfortunate but I opted for local consistency for
> now.
> 
> -- >8 --
> 
> Unlike for span<X> and empty_view<X>, the range_reference_t of
> ref_view<X> doesn't correspond to X.  This patch fixes the ref_view
> branch of views::as_const to correctly query the underlying range
> type X.
> 
>       PR libstdc++/119135
> 
> libstdc++-v3/ChangeLog:
> 
>       * include/std/ranges: Include <utility>.
>       (views::__detail::__is_ref_view): Replace with ...
>       (views::__detail::__is_constable_ref_view): ... this.
>       (views::_AsConst::operator()): Correct the ref_view branch.
>       * testsuite/std/ranges/adaptors/as_const/1.cc (test03): Extend
>       test.
> ---
>  libstdc++-v3/include/std/ranges                      | 12 ++++++------
>  .../testsuite/std/ranges/adaptors/as_const/1.cc      |  4 ++++
>  2 files changed, 10 insertions(+), 6 deletions(-)
> 
> diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges
> index c2a2d6f4e05..31d62454895 100644
> --- a/libstdc++-v3/include/std/ranges
> +++ b/libstdc++-v3/include/std/ranges
> @@ -48,6 +48,7 @@
>  #include <string_view>
>  #include <tuple>
>  #if __cplusplus > 202002L
> +#include <utility>
>  #include <variant>
>  #endif
>  #include <bits/ranges_util.h>
> @@ -9324,10 +9325,11 @@ namespace views::__adaptor
>      namespace __detail
>      {
>        template<typename _Tp>
> -     inline constexpr bool __is_ref_view = false;
> +     inline constexpr bool __is_constable_ref_view = false;
>  
>        template<typename _Range>
> -     inline constexpr bool __is_ref_view<ref_view<_Range>> = true;
> +     inline constexpr bool __is_constable_ref_view<ref_view<_Range>>
> +       = constant_range<const _Range>;
>  
>        template<typename _Range>
>       concept __can_as_const_view = requires { 
> as_const_view(std::declval<_Range>()); };
> @@ -9349,10 +9351,8 @@ namespace views::__adaptor
>         return views::empty<const element_type>;
>       else if constexpr (std::__detail::__is_span<_Tp>)
>         return span<const element_type, 
> _Tp::extent>(std::forward<_Range>(__r));
> -     else if constexpr (__detail::__is_ref_view<_Tp>
> -                        && constant_range<const element_type>)
> -       return ref_view(static_cast<const element_type&>
> -                       (std::forward<_Range>(__r).base()));
> +     else if constexpr (__detail::__is_constable_ref_view<_Tp>)
> +       return ref_view(std::as_const(__r.base()));

Whoops, just noticed that I got rid of the perfect forwarding of __r
here for no good reason.  It shouldn't matter since its base() member
function is const, but consider the std::forward restored for
consistency.

>       else if constexpr (is_lvalue_reference_v<_Range>
>                          && constant_range<const _Tp>
>                          && !view<_Tp>)
> diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/as_const/1.cc 
> b/libstdc++-v3/testsuite/std/ranges/adaptors/as_const/1.cc
> index c36786a8c5f..3f1f8eb1772 100644
> --- a/libstdc++-v3/testsuite/std/ranges/adaptors/as_const/1.cc
> +++ b/libstdc++-v3/testsuite/std/ranges/adaptors/as_const/1.cc
> @@ -63,6 +63,10 @@ test03()
>    std::vector<int> v;
>    std::same_as<ranges::ref_view<const std::vector<int>>>
>      auto r = views::as_const(v);
> +
> +  // PR libstdc++/119135
> +  std::same_as<ranges::ref_view<const std::vector<int>>>
> +    auto r2 = views::as_const(views::all(v));
>  }
>  
>  int
> -- 
> 2.49.0.rc1.37.ge969bc8759
> 
> 

Reply via email to