mirror of
https://github.com/gcc-mirror/gcc.git
synced 2026-05-06 14:59:39 +02:00
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>
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user