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