[PATCH] libstdc++: Fix ref_view branch of views::as_const [PR119135]

Patrick Palka ppalka@redhat.com
Thu Mar 13 03:45:25 GMT 2025


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



More information about the Libstdc++ mailing list