libstdc++: Sync concat_view with final P2542 revision [PR115209]

Our concat_view implementation is 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, which this patch updates.

This patch also simplifies the concat_view::end wording via C++26 pack
indexing as per the final revision.  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.

Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
This commit is contained in:
Patrick Palka 2025-02-19 22:59:49 -05:00
parent 6d8e9cdbac
commit 8543dc52d8
3 changed files with 18 additions and 23 deletions

View file

@ -1842,6 +1842,7 @@ ftms = {
values = {
v = 202403;
cxxmin = 26;
extra_cond = "__cpp_pack_indexing";
};
};

View file

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

View file

@ -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)