From: Tomasz Kamiński Date: Fri, 24 Apr 2026 13:10:41 +0000 (+0200) Subject: libsdc++: Restore check for validity of std::get for elements_view. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=490eca9b76ec201356d6defacaa8231a64a2102d;p=thirdparty%2Fgcc.git libsdc++: Restore check for validity of std::get for elements_view. Resolves LWG3797, "elements_view insufficiently constrained". When P2165R4 updated __has_tuple_element in C++23 to reuse __tuple_like concept, it dropped the requirement of validity of get, assuming that for tuple_like type with size of N, get on lvalue is well-formed for any I < N. This however does not hold for ranges::subrange (tuple-like of size 2) with move-only iterator, for which get can only be applied on rvalue. In consequence constrains allowed instantiating elements_view for range of such subrange, but instantiating it's iterator lead to hard error from iterator_category computation. This patch applies the requirements on validity of get also in C++23 and later standard modes. libstdc++-v3/ChangeLog: * include/std/ranges (__detail::__has_tuple_element): Check if std::get<_Nm>(__t) returns referenceable type also for C++23 and later. * testsuite/std/ranges/adaptors/elements.cc: Add test covering vector of ranges::subrange with move-only iterator. Reviewed-by: Patrick Palka Signed-off-by: Tomasz Kamiński --- diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges index 55d3c520ba4..7d8b37f8c5c 100644 --- a/libstdc++-v3/include/std/ranges +++ b/libstdc++-v3/include/std/ranges @@ -4355,8 +4355,15 @@ namespace views::__adaptor namespace __detail { #if __cpp_lib_tuple_like // >= C++23 + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3797. elements_view insufficiently constrained template - concept __has_tuple_element = __tuple_like<_Tp> && _Nm < tuple_size_v<_Tp>; + concept __has_tuple_element = __tuple_like<_Tp> && _Nm < tuple_size_v<_Tp> + && requires(_Tp __t) + { + { std::get<_Nm>(__t) } + -> convertible_to&>; + }; #else template concept __has_tuple_element = requires(_Tp __t) diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/elements.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/elements.cc index 5237d787e7b..d384cfd5adf 100644 --- a/libstdc++-v3/testsuite/std/ranges/adaptors/elements.cc +++ b/libstdc++-v3/testsuite/std/ranges/adaptors/elements.cc @@ -27,6 +27,22 @@ namespace ranges = std::ranges; namespace views = ranges::views; +template +concept can_elements = requires (Rg&& rg) +{ views::elements<0>(rg); }; + +static_assert( !can_elements<0, std::vector> ); +static_assert( can_elements<0, std::tuple[4]> ); +static_assert( can_elements<1, std::vector>> ); + +// Test LWG 3797. elements_view insufficiently constrained +using move_only_iter_range = __gnu_test::test_input_range_nocopy; +using move_only_iter_subrange = ranges::subrange< + ranges::iterator_t, + ranges::sentinel_t>; +static_assert( can_elements<0, std::vector>> ); +static_assert( !can_elements<0, std::vector> ); + void test01() {