https://gcc.gnu.org/g:612690936f5ddd122b60cf843cb4f40ae7ede436
commit r15-9917-g612690936f5ddd122b60cf843cb4f40ae7ede436 Author: Patrick Palka <ppa...@redhat.com> Date: Thu Jul 3 10:55:17 2025 -0400 libstdc++: Update LWG 4166 changes to concat_view::end() [PR120934] In r15-4555-gf191c830154565 we proactively implemented the initial proposed resolution for LWG 4166 which later turned out to be insufficient, since we must also require equality_comparable of the underlying iterators before concat_view could be a common range. This patch implements the updated P/R, requiring all underlying iterators to be forward (which implies equality_comparable) before making concat_view common, which fixes the testcase from this PR. PR libstdc++/120934 libstdc++-v3/ChangeLog: * include/std/ranges (concat_view::end): Refine condition for returning an iterator instead of default_sentinel as per the updated P/R for LWG 4166. * testsuite/std/ranges/concat/1.cc (test05): New test. Reviewed-by: Jonathan Wakely <jwak...@redhat.com> (cherry picked from commit c5a17e92ebf0c6f3887fb5698a1114a3fdf50576) Diff: --- libstdc++-v3/include/std/ranges | 4 ++-- libstdc++-v3/testsuite/std/ranges/concat/1.cc | 13 +++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges index 210ac8274fc1..87560dddd65d 100644 --- a/libstdc++-v3/include/std/ranges +++ b/libstdc++-v3/include/std/ranges @@ -9735,7 +9735,7 @@ namespace ranges end() requires (!(__detail::__simple_view<_Vs> && ...)) { constexpr auto __n = sizeof...(_Vs); - if constexpr ((semiregular<iterator_t<_Vs>> && ...) + if constexpr (__detail::__all_forward<false, _Vs...> && common_range<_Vs...[__n - 1]>) return _Iterator<false>(this, in_place_index<__n - 1>, ranges::end(std::get<__n - 1>(_M_views))); @@ -9747,7 +9747,7 @@ namespace ranges end() const requires (range<const _Vs> && ...) && __detail::__concatable<const _Vs...> { constexpr auto __n = sizeof...(_Vs); - if constexpr ((semiregular<iterator_t<const _Vs>> && ...) + if constexpr (__detail::__all_forward<true, _Vs...> && common_range<const _Vs...[__n - 1]>) return _Iterator<true>(this, in_place_index<__n - 1>, ranges::end(std::get<__n - 1>(_M_views))); diff --git a/libstdc++-v3/testsuite/std/ranges/concat/1.cc b/libstdc++-v3/testsuite/std/ranges/concat/1.cc index 16721912a37d..f78ed08a610b 100644 --- a/libstdc++-v3/testsuite/std/ranges/concat/1.cc +++ b/libstdc++-v3/testsuite/std/ranges/concat/1.cc @@ -99,6 +99,18 @@ test04() using type = decltype(v); } +void +test05() +{ + // PR libstdc++/120934 - views::concat is ill-formed depending on argument order + auto v1 = views::single(1); + std::vector<int> vec = {2, 3}; + auto v2 = views::join(views::transform(vec, views::single)); + + static_assert( ranges::range<decltype(views::concat(v1, v2))> ); + static_assert( ranges::range<decltype(views::concat(v2, v1))> ); +} + int main() { @@ -107,4 +119,5 @@ main() test02(); test03(); test04(); + test05(); }