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