[gcc r17-72] libsdc++: Restore check for validity of std::get for elements_view.

Tomasz Kaminski tkaminsk@gcc.gnu.org
Fri Apr 24 14:59:47 GMT 2026


https://gcc.gnu.org/g:490eca9b76ec201356d6defacaa8231a64a2102d

commit r17-72-g490eca9b76ec201356d6defacaa8231a64a2102d
Author: Tomasz Kamiński <tkaminsk@redhat.com>
Date:   Fri Apr 24 15:10:41 2026 +0200

    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<I> 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 <ppalka@redhat.com>
    Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>

Diff:
---
 libstdc++-v3/include/std/ranges                        |  9 ++++++++-
 libstdc++-v3/testsuite/std/ranges/adaptors/elements.cc | 16 ++++++++++++++++
 2 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges
index 55d3c520ba4c..7d8b37f8c5cf 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<typename _Tp, size_t _Nm>
-    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<const tuple_element_t<_Nm, _Tp>&>;
+	 };
 #else
     template<typename _Tp, size_t _Nm>
     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 5237d787e7b2..d384cfd5adf3 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<size_t N, typename Rg>
+concept can_elements = requires (Rg&& rg)
+{ views::elements<0>(rg); };
+
+static_assert( !can_elements<0, std::vector<int>> );
+static_assert( can_elements<0, std::tuple<int>[4]> );
+static_assert( can_elements<1, std::vector<std::pair<int, int>>> );
+
+// Test LWG 3797. elements_view insufficiently constrained
+using move_only_iter_range = __gnu_test::test_input_range_nocopy<int>;
+using move_only_iter_subrange = ranges::subrange<
+  ranges::iterator_t<move_only_iter_range>,
+  ranges::sentinel_t<move_only_iter_range>>;
+static_assert( can_elements<0, std::vector<ranges::subrange<int*>>> );
+static_assert( !can_elements<0, std::vector<move_only_iter_subrange>> );
+
 void
 test01()
 {


More information about the Libstdc++-cvs mailing list