From: Patrick Palka Date: Tue, 22 Oct 2024 21:01:59 +0000 (-0400) Subject: libstdc++: Implement LWG 4166 changes to concat_view::end() X-Git-Tag: basepoints/gcc-16~4998 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f191c8301545658543773ba3d0e6f3f0927529e0;p=thirdparty%2Fgcc.git libstdc++: Implement LWG 4166 changes to concat_view::end() This patch proactively implements the proposed resolution for this LWG issue, which seems straightforward and slated to get approved as-is. (No _GLIBCXX_RESOLVE_LIB_DEFECTS code comment is added since concat_view is C++26, so this isn't a defect against a published standard.) libstdc++-v3/ChangeLog: * include/std/ranges (concat_view::begin): Add space after 'requires' starting a requires-clause. (concat_view::end): Likewise. Refine condition for returning an iterator rather than default_sentinel as per LWG 4166. * testsuite/std/ranges/concat/1.cc (test03): Verify LWG 4166 example. Reviewed-by: Jonathan Wakely --- diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges index 9f233729d9c7..cebe10683f91 100644 --- a/libstdc++-v3/include/std/ranges +++ b/libstdc++-v3/include/std/ranges @@ -9687,7 +9687,7 @@ namespace ranges { } constexpr iterator - begin() requires(!(__detail::__simple_view<_Vs> && ...)) + begin() requires (!(__detail::__simple_view<_Vs> && ...)) { iterator __it(this, in_place_index<0>, ranges::begin(std::get<0>(_M_views))); __it.template _M_satisfy<0>(); @@ -9703,9 +9703,10 @@ namespace ranges } constexpr auto - end() requires(!(__detail::__simple_view<_Vs> && ...)) + end() requires (!(__detail::__simple_view<_Vs> && ...)) { - if constexpr (__detail::__last_is_common<_Vs...>::value) + if constexpr ((semiregular> && ...) + && __detail::__last_is_common<_Vs...>::value) { constexpr auto __n = sizeof...(_Vs); return iterator(this, in_place_index<__n - 1>, @@ -9718,7 +9719,8 @@ namespace ranges constexpr auto end() const requires (range && ...) && __detail::__concatable { - if constexpr (__detail::__last_is_common::value) + if constexpr ((semiregular> && ...) + && __detail::__last_is_common::value) { constexpr auto __n = sizeof...(_Vs); return iterator(this, in_place_index<__n - 1>, diff --git a/libstdc++-v3/testsuite/std/ranges/concat/1.cc b/libstdc++-v3/testsuite/std/ranges/concat/1.cc index 6ffe28ece511..e5d10f476e93 100644 --- a/libstdc++-v3/testsuite/std/ranges/concat/1.cc +++ b/libstdc++-v3/testsuite/std/ranges/concat/1.cc @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -66,9 +67,28 @@ test02() VERIFY( ranges::equal(v | views::drop(1), x) ); } +void +test03() +{ + // LWG 4166 - concat_view::end() should be more constrained in order to + // support noncopyable iterators + auto range_copyable_it = std::vector{1, 2, 3}; + + std::stringstream ss{"4 5 6"}; + auto range_noncopyable_it = views::istream(ss); + ranges::range auto view1 = views::concat(range_copyable_it, range_noncopyable_it); + VERIFY( ranges::equal(view1, std::vector{1, 2, 3, 4, 5, 6}) ); + + ss = std::stringstream{"4 5 6"}; + range_noncopyable_it = views::istream(ss); + ranges::range auto view2 = views::concat(range_noncopyable_it, range_copyable_it); + VERIFY( ranges::equal(view2, std::vector{4, 5, 6, 1, 2, 3}) ); +} + int main() { static_assert(test01()); test02(); + test03(); }