On Wed, 12 Mar 2025, Patrick Palka wrote:
> 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.
Like so:
-- >8 --
Subject: [PATCH v2] libstdc++: Fix ref_view branch of views::as_const [PR119135]
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 its 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..ef277b81bd3 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(std::forward<_Range>(__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