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())); 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