]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libstdc++: Fix get<0> constraint for lvalue ranges::subrange (LWG 3589)
authorJonathan Wakely <jwakely@redhat.com>
Thu, 14 Nov 2024 17:31:43 +0000 (17:31 +0000)
committerJonathan Wakely <jwakely@redhat.com>
Wed, 16 Apr 2025 17:50:42 +0000 (18:50 +0100)
Approved at October 2021 plenary.

libstdc++-v3/ChangeLog:

* include/bits/ranges_util.h (subrange::begin): Fix constraint,
as per LWG 3589.
* testsuite/std/ranges/subrange/lwg3589.cc: New test.

(cherry picked from commit 4a3a0be34f723df192361e43bb48b9292dfe3a54)

libstdc++-v3/include/bits/ranges_util.h
libstdc++-v3/testsuite/std/ranges/subrange/lwg3589.cc [new file with mode: 0644]

index 37d7bc862f9fbc4c74dd5c333f2c6dc44ac134b5..5299ce193c934e17d773249e6a5575e6c4648e98 100644 (file)
@@ -399,8 +399,11 @@ namespace ranges
             __detail::__make_unsigned_like_t<range_difference_t<_Rng>>)
       -> subrange<iterator_t<_Rng>, sentinel_t<_Rng>, subrange_kind::sized>;
 
+  // _GLIBCXX_RESOLVE_LIB_DEFECTS
+  // 3589. The const lvalue reference overload of get for subrange does not
+  // constrain I to be copyable when N == 0
   template<size_t _Num, class _It, class _Sent, subrange_kind _Kind>
-    requires (_Num < 2)
+    requires ((_Num == 0 && copyable<_It>) || _Num == 1)
     constexpr auto
     get(const subrange<_It, _Sent, _Kind>& __r)
     {
diff --git a/libstdc++-v3/testsuite/std/ranges/subrange/lwg3589.cc b/libstdc++-v3/testsuite/std/ranges/subrange/lwg3589.cc
new file mode 100644 (file)
index 0000000..1ccc52d
--- /dev/null
@@ -0,0 +1,30 @@
+// { dg-do compile { target c++20 } }
+
+// LWG 3589. The const lvalue reference overload of get for subrange does not
+// constrain I to be copyable when N == 0
+
+#include <ranges>
+#include <testsuite_iterators.h>
+
+void
+test_lwg3589()
+{
+  int a[2]{};
+  __gnu_test::test_range<int, __gnu_test::input_iterator_wrapper_nocopy> r(a);
+
+  // Use a generic lambda so we have a dependent context.
+  auto test = [](auto& x)
+    {
+      // This was wrong before the LWG 3589 change:
+      if constexpr (requires { std::ranges::get<0>(x); })
+       (void) std::ranges::get<0>(x);
+
+      // These always worked unconditionally:
+      (void) std::ranges::get<1>(x);
+      (void) std::ranges::get<0>(std::move(x));
+      (void) std::ranges::get<1>(std::move(x));
+    };
+
+  std::ranges::subrange sr(r.begin(), r.end());
+  test(sr);
+}