https://gcc.gnu.org/g:8fda1b0f513129861729eed25067438031fb6ec5
commit r13-9242-g8fda1b0f513129861729eed25067438031fb6ec5 Author: Jonathan Wakely <jwak...@redhat.com> Date: Thu Nov 14 17:31:43 2024 +0000 libstdc++: Fix get<0> constraint for lvalue ranges::subrange (LWG 3589) 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) Diff: --- libstdc++-v3/include/bits/ranges_util.h | 5 +++- .../testsuite/std/ranges/subrange/lwg3589.cc | 30 ++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/libstdc++-v3/include/bits/ranges_util.h b/libstdc++-v3/include/bits/ranges_util.h index 5f6a1d360ed0..ddb0260c3772 100644 --- a/libstdc++-v3/include/bits/ranges_util.h +++ b/libstdc++-v3/include/bits/ranges_util.h @@ -432,8 +432,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 index 000000000000..1ccc52d81f8a --- /dev/null +++ b/libstdc++-v3/testsuite/std/ranges/subrange/lwg3589.cc @@ -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); +}