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)
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()
{