On Wed, 19 Feb 2025, Patrick Palka wrote:
> On Wed, 19 Feb 2025, Jonathan Wakely wrote:
>
> > On Tue, 18 Feb 2025 at 04:11, Patrick Palka <[email protected]> wrote:
> > >
> > > Tested on x86_64-pc-linux-gnu, does this look OK for trunk?
> > >
> > > -- >8 --
> > >
> > > The original implementation was accidentally based off of an older
> > > revision of the paper, P2542R7 instead of R8. As far as I can tell
> > > the only semantic change in the final revision is the relaxed
> > > constraints on the iterator's iter/sent operator- overloads.
> > >
> > > The revision also simplifies the concat_view::end wording via C++26
> > > pack indexing, which GCC 15 and Clang 19/20 implement so we can use
> > > it unconditionally here and remove the __last_is_common helper trait.
> >
> > What about Clang 18 with -std=c++26?
> >
> > I'd be OK with making the ranges_concat macro depend on the one for
> > pack indexing though.
>
> Sounds good. Clang 18 doesn't implement pack indexing, so it'd
> otherwise break <ranges> in C++26 there.
Like so?
-- >8 --
Subject: [PATCH] libstdc++: Sync concat_view with final P2542 revision
[PR115209]
The original implementation was accidentally based off of an older
revision of the paper, P2542R7 instead of R8. As far as I can tell
the only semantic change in the final revision is the relaxed
constraints on the iterator's iter/sent operator- overloads.
The revision also simplifies the concat_view::end wording via C++26 pack
indexing, which is reflected here. In turn we make the availability of
this library feature conditional on __cpp_pack_indexing. (Note pack
indexing is implemented in GCC 15 and Clang 19).
PR libstdc++/115209
libstdc++-v3/ChangeLog:
* include/bits/version.def (ranges_concat): Depend on
__cpp_pack_indexing.
* include/bits/version.h: Regenerate.
* include/std/ranges (__detail::__last_is_common): Remove.
(__detail::__all_but_first_sized): New.
(concat_view::end): Use C++26 pack indexing instead of
__last_is_common as per R8 of P2542.
(concat_view::iterator::operator-): Update constraints on
iter/sent overloads as per R8 of P2542.
---
libstdc++-v3/include/bits/version.def | 1 +
libstdc++-v3/include/bits/version.h | 2 +-
libstdc++-v3/include/std/ranges | 38 +++++++++++----------------
3 files changed, 18 insertions(+), 23 deletions(-)
diff --git a/libstdc++-v3/include/bits/version.def
b/libstdc++-v3/include/bits/version.def
index 002e560dc0d..e75befe7f4b 100644
--- a/libstdc++-v3/include/bits/version.def
+++ b/libstdc++-v3/include/bits/version.def
@@ -1842,6 +1842,7 @@ ftms = {
values = {
v = 202403;
cxxmin = 26;
+ extra_cond = "__cpp_pack_indexing";
};
};
diff --git a/libstdc++-v3/include/bits/version.h
b/libstdc++-v3/include/bits/version.h
index 70de189b1e0..cd713ee54ea 100644
--- a/libstdc++-v3/include/bits/version.h
+++ b/libstdc++-v3/include/bits/version.h
@@ -2036,7 +2036,7 @@
#undef __glibcxx_want_is_virtual_base_of
#if !defined(__cpp_lib_ranges_concat)
-# if (__cplusplus > 202302L)
+# if (__cplusplus > 202302L) && (__cpp_pack_indexing)
# define __glibcxx_ranges_concat 202403L
# if defined(__glibcxx_want_all) || defined(__glibcxx_want_ranges_concat)
# define __cpp_lib_ranges_concat 202403L
diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges
index 5c795a90fbc..22e0c9cae44 100644
--- a/libstdc++-v3/include/std/ranges
+++ b/libstdc++-v3/include/std/ranges
@@ -9683,12 +9683,8 @@ namespace ranges
&& __all_but_last_common<_Const, _Rs...>::value;
template<typename _Range, typename... _Rs>
- struct __last_is_common
- { static inline constexpr bool value = __last_is_common<_Rs...>::value;
};
-
- template<typename _Range>
- struct __last_is_common<_Range>
- { static inline constexpr bool value = common_range<_Range>; };
+ struct __all_but_first_sized
+ { static inline constexpr bool value = (sized_range<_Rs> && ...); };
} // namespace __detail
template<input_range... _Vs>
@@ -9726,13 +9722,11 @@ namespace ranges
constexpr auto
end() requires (!(__detail::__simple_view<_Vs> && ...))
{
+ constexpr auto __n = sizeof...(_Vs);
if constexpr ((semiregular<iterator_t<_Vs>> && ...)
- && __detail::__last_is_common<_Vs...>::value)
- {
- constexpr auto __n = sizeof...(_Vs);
- return iterator<false>(this, in_place_index<__n - 1>,
- ranges::end(std::get<__n - 1>(_M_views)));
- }
+ && common_range<_Vs...[__n - 1]>)
+ return iterator<false>(this, in_place_index<__n - 1>,
+ ranges::end(std::get<__n - 1>(_M_views)));
else
return default_sentinel;
}
@@ -9740,13 +9734,11 @@ namespace ranges
constexpr auto
end() const requires (range<const _Vs> && ...) &&
__detail::__concatable<const _Vs...>
{
+ constexpr auto __n = sizeof...(_Vs);
if constexpr ((semiregular<iterator_t<const _Vs>> && ...)
- && __detail::__last_is_common<const _Vs...>::value)
- {
- constexpr auto __n = sizeof...(_Vs);
- return iterator<true>(this, in_place_index<__n - 1>,
- ranges::end(std::get<__n - 1>(_M_views)));
- }
+ && common_range<const _Vs...[__n - 1]>)
+ return iterator<true>(this, in_place_index<__n - 1>,
+ ranges::end(std::get<__n - 1>(_M_views)));
else
return default_sentinel;
}
@@ -10128,8 +10120,9 @@ namespace ranges
friend constexpr difference_type
operator-(const iterator& __x, default_sentinel_t)
- requires __detail::__concat_is_random_access<_Const, _Vs...>
- && __detail::__last_is_common<__maybe_const_t<_Const, _Vs>...>::value
+ requires (sized_sentinel_for<sentinel_t<__maybe_const_t<_Const, _Vs>>,
+ iterator_t<__maybe_const_t<_Const, _Vs>>> &&
...)
+ && __detail::__all_but_first_sized<__maybe_const_t<_Const,
_Vs>...>::value
{
return _S_invoke_with_runtime_index([&]<size_t _Ix>() -> difference_type
{
auto __dx = ranges::distance(std::get<_Ix>(__x._M_it),
@@ -10148,8 +10141,9 @@ namespace ranges
friend constexpr difference_type
operator-(default_sentinel_t, const iterator& __x)
- requires __detail::__concat_is_random_access<_Const, _Vs...>
- && __detail::__last_is_common<__maybe_const_t<_Const, _Vs>...>::value
+ requires (sized_sentinel_for<sentinel_t<__maybe_const_t<_Const, _Vs>>,
+ iterator_t<__maybe_const_t<_Const, _Vs>>> &&
...)
+ && __detail::__all_but_first_sized<__maybe_const_t<_Const,
_Vs>...>::value
{ return -(__x - default_sentinel); }
friend constexpr decltype(auto)
--
2.48.1.385.ga554262210.dirty
>
> >
> > As I noted in bugzilla, the conct_view::iterator type should be named
> > _Iterator
>
> Will fix
>
> >
> >
> > >
> > > PR libstdc++/115209
> > >
> > > libstdc++-v3/ChangeLog:
> > >
> > > * include/std/ranges (__detail::__last_is_common): Remove.
> > > (__detail::__all_but_first_sized): New.
> > > (concat_view::end): Use C++26 pack indexing instead of
> > > __last_is_common as per P2542R8.
> > > (concat_view::iterator::operator-): Update constraints on
> > > iter/sent overloads as per P2542R7.
> > > ---
> > > libstdc++-v3/include/std/ranges | 38 ++++++++++++++-------------------
> > > 1 file changed, 16 insertions(+), 22 deletions(-)
> > >
> > > diff --git a/libstdc++-v3/include/std/ranges
> > > b/libstdc++-v3/include/std/ranges
> > > index 5c795a90fbc..22e0c9cae44 100644
> > > --- a/libstdc++-v3/include/std/ranges
> > > +++ b/libstdc++-v3/include/std/ranges
> > > @@ -9683,12 +9683,8 @@ namespace ranges
> > > && __all_but_last_common<_Const, _Rs...>::value;
> > >
> > > template<typename _Range, typename... _Rs>
> > > - struct __last_is_common
> > > - { static inline constexpr bool value =
> > > __last_is_common<_Rs...>::value; };
> > > -
> > > - template<typename _Range>
> > > - struct __last_is_common<_Range>
> > > - { static inline constexpr bool value = common_range<_Range>; };
> > > + struct __all_but_first_sized
> > > + { static inline constexpr bool value = (sized_range<_Rs> && ...);
> > > };
> > > } // namespace __detail
> > >
> > > template<input_range... _Vs>
> > > @@ -9726,13 +9722,11 @@ namespace ranges
> > > constexpr auto
> > > end() requires (!(__detail::__simple_view<_Vs> && ...))
> > > {
> > > + constexpr auto __n = sizeof...(_Vs);
> > > if constexpr ((semiregular<iterator_t<_Vs>> && ...)
> > > - && __detail::__last_is_common<_Vs...>::value)
> > > - {
> > > - constexpr auto __n = sizeof...(_Vs);
> > > - return iterator<false>(this, in_place_index<__n - 1>,
> > > - ranges::end(std::get<__n -
> > > 1>(_M_views)));
> > > - }
> > > + && common_range<_Vs...[__n - 1]>)
> > > + return iterator<false>(this, in_place_index<__n - 1>,
> > > + ranges::end(std::get<__n - 1>(_M_views)));
> > > else
> > > return default_sentinel;
> > > }
> > > @@ -9740,13 +9734,11 @@ namespace ranges
> > > constexpr auto
> > > end() const requires (range<const _Vs> && ...) &&
> > > __detail::__concatable<const _Vs...>
> > > {
> > > + constexpr auto __n = sizeof...(_Vs);
> > > if constexpr ((semiregular<iterator_t<const _Vs>> && ...)
> > > - && __detail::__last_is_common<const _Vs...>::value)
> > > - {
> > > - constexpr auto __n = sizeof...(_Vs);
> > > - return iterator<true>(this, in_place_index<__n - 1>,
> > > - ranges::end(std::get<__n - 1>(_M_views)));
> > > - }
> > > + && common_range<const _Vs...[__n - 1]>)
> > > + return iterator<true>(this, in_place_index<__n - 1>,
> > > + ranges::end(std::get<__n - 1>(_M_views)));
> > > else
> > > return default_sentinel;
> > > }
> > > @@ -10128,8 +10120,9 @@ namespace ranges
> > >
> > > friend constexpr difference_type
> > > operator-(const iterator& __x, default_sentinel_t)
> > > - requires __detail::__concat_is_random_access<_Const, _Vs...>
> > > - && __detail::__last_is_common<__maybe_const_t<_Const,
> > > _Vs>...>::value
> > > + requires (sized_sentinel_for<sentinel_t<__maybe_const_t<_Const,
> > > _Vs>>,
> > > + iterator_t<__maybe_const_t<_Const,
> > > _Vs>>> && ...)
> > > + && __detail::__all_but_first_sized<__maybe_const_t<_Const,
> > > _Vs>...>::value
> > > {
> > > return _S_invoke_with_runtime_index([&]<size_t _Ix>() ->
> > > difference_type {
> > > auto __dx = ranges::distance(std::get<_Ix>(__x._M_it),
> > > @@ -10148,8 +10141,9 @@ namespace ranges
> > >
> > > friend constexpr difference_type
> > > operator-(default_sentinel_t, const iterator& __x)
> > > - requires __detail::__concat_is_random_access<_Const, _Vs...>
> > > - && __detail::__last_is_common<__maybe_const_t<_Const,
> > > _Vs>...>::value
> > > + requires (sized_sentinel_for<sentinel_t<__maybe_const_t<_Const,
> > > _Vs>>,
> > > + iterator_t<__maybe_const_t<_Const,
> > > _Vs>>> && ...)
> > > + && __detail::__all_but_first_sized<__maybe_const_t<_Const,
> > > _Vs>...>::value
> > > { return -(__x - default_sentinel); }
> > >
> > > friend constexpr decltype(auto)
> > > --
> > > 2.48.1.356.g0394451348.dirty
> > >
> >
> >
>