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? -- >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 > > > > > > > >