https://gcc.gnu.org/g:f191c8301545658543773ba3d0e6f3f0927529e0

commit r15-4555-gf191c8301545658543773ba3d0e6f3f0927529e0
Author: Patrick Palka <ppa...@redhat.com>
Date:   Tue Oct 22 17:01:59 2024 -0400

    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 <jwak...@redhat.com>

Diff:
---
 libstdc++-v3/include/std/ranges               | 10 ++++++----
 libstdc++-v3/testsuite/std/ranges/concat/1.cc | 20 ++++++++++++++++++++
 2 files changed, 26 insertions(+), 4 deletions(-)

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<false>
-    begin() requires(!(__detail::__simple_view<_Vs> && ...))
+    begin() requires (!(__detail::__simple_view<_Vs> && ...))
     {
       iterator<false> __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<iterator_t<_Vs>> && ...)
+                   && __detail::__last_is_common<_Vs...>::value)
        {
          constexpr auto __n = sizeof...(_Vs);
          return iterator<false>(this, in_place_index<__n - 1>,
@@ -9718,7 +9719,8 @@ namespace ranges
     constexpr auto
     end() const requires (range<const _Vs> && ...) && 
__detail::__concatable<const _Vs...>
     {
-      if constexpr (__detail::__last_is_common<const _Vs...>::value)
+      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>,
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 <algorithm>
 #include <vector>
 #include <array>
+#include <sstream>
 #include <utility>
 #include <testsuite_hooks.h>
 #include <testsuite_iterators.h>
@@ -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<int>{1, 2, 3};
+
+  std::stringstream ss{"4 5 6"};
+  auto range_noncopyable_it = views::istream<int>(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<int>(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();
 }

Reply via email to