On Wed, 19 Feb 2025 at 14:57, Patrick Palka <ppa...@redhat.com> wrote: > > 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 <ppa...@redhat.com> 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?
OK for trunk, thanks. > > -- >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 > > > > > > > > > > > > >