libstdc++: Fix elements_view::operator* and operator[] [LWG 3502]
While we're modifying elements_view, this also implements the one-line resolution of LWG 3492. libstdc++-v3/ChangeLog: * include/std/ranges (__detail::__returnable_element): New concept. (elements_view): Use this concept in its constraints. Add missing private access specifier. (elements_view::_S_get_element): Define as per LWG 3502. (elements_view::operator*, elements_view::operator[]): Use _S_get_element. (elements_view::operator++): Remove unnecessary constraint as per LWG 3492. * testsuite/std/ranges/adaptors/elements.cc (test05): New test.
This commit is contained in:
parent
be8d5f99f5
commit
c7fe68f365
@ -3234,6 +3234,10 @@ namespace views::__adaptor
|
|||||||
{ std::get<_Nm>(__t) }
|
{ std::get<_Nm>(__t) }
|
||||||
-> convertible_to<const tuple_element_t<_Nm, _Tp>&>;
|
-> convertible_to<const tuple_element_t<_Nm, _Tp>&>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename _Tp, size_t _Nm>
|
||||||
|
concept __returnable_element
|
||||||
|
= is_reference_v<_Tp> || move_constructible<tuple_element_t<_Nm, _Tp>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<input_range _Vp, size_t _Nm>
|
template<input_range _Vp, size_t _Nm>
|
||||||
@ -3241,6 +3245,7 @@ namespace views::__adaptor
|
|||||||
&& __detail::__has_tuple_element<range_value_t<_Vp>, _Nm>
|
&& __detail::__has_tuple_element<range_value_t<_Vp>, _Nm>
|
||||||
&& __detail::__has_tuple_element<remove_reference_t<range_reference_t<_Vp>>,
|
&& __detail::__has_tuple_element<remove_reference_t<range_reference_t<_Vp>>,
|
||||||
_Nm>
|
_Nm>
|
||||||
|
&& __detail::__returnable_element<range_reference_t<_Vp>, _Nm>
|
||||||
class elements_view : public view_interface<elements_view<_Vp, _Nm>>
|
class elements_view : public view_interface<elements_view<_Vp, _Nm>>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -3298,10 +3303,23 @@ namespace views::__adaptor
|
|||||||
template<bool _Const>
|
template<bool _Const>
|
||||||
struct _Iterator
|
struct _Iterator
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
using _Base = __detail::__maybe_const_t<_Const, _Vp>;
|
using _Base = __detail::__maybe_const_t<_Const, _Vp>;
|
||||||
|
|
||||||
iterator_t<_Base> _M_current = iterator_t<_Base>();
|
iterator_t<_Base> _M_current = iterator_t<_Base>();
|
||||||
|
|
||||||
|
static constexpr decltype(auto)
|
||||||
|
_S_get_element(const iterator_t<_Base>& __i)
|
||||||
|
{
|
||||||
|
if constexpr (is_reference_v<range_reference_t<_Base>>)
|
||||||
|
return std::get<_Nm>(*__i);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
using _Et = remove_cv_t<tuple_element_t<_Nm, range_reference_t<_Base>>>;
|
||||||
|
return static_cast<_Et>(std::get<_Nm>(*__i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
friend _Iterator<!_Const>;
|
friend _Iterator<!_Const>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -3334,8 +3352,8 @@ namespace views::__adaptor
|
|||||||
{ return std::move(_M_current); }
|
{ return std::move(_M_current); }
|
||||||
|
|
||||||
constexpr decltype(auto)
|
constexpr decltype(auto)
|
||||||
operator*() const
|
operator*() const
|
||||||
{ return std::get<_Nm>(*_M_current); }
|
{ return _S_get_element(_M_current); }
|
||||||
|
|
||||||
constexpr _Iterator&
|
constexpr _Iterator&
|
||||||
operator++()
|
operator++()
|
||||||
@ -3345,7 +3363,7 @@ namespace views::__adaptor
|
|||||||
}
|
}
|
||||||
|
|
||||||
constexpr void
|
constexpr void
|
||||||
operator++(int) requires (!forward_range<_Base>)
|
operator++(int)
|
||||||
{ ++_M_current; }
|
{ ++_M_current; }
|
||||||
|
|
||||||
constexpr _Iterator
|
constexpr _Iterator
|
||||||
@ -3390,7 +3408,7 @@ namespace views::__adaptor
|
|||||||
constexpr decltype(auto)
|
constexpr decltype(auto)
|
||||||
operator[](difference_type __n) const
|
operator[](difference_type __n) const
|
||||||
requires random_access_range<_Base>
|
requires random_access_range<_Base>
|
||||||
{ return std::get<_Nm>(*(_M_current + __n)); }
|
{ return _S_get_element(_M_current + __n); }
|
||||||
|
|
||||||
friend constexpr bool
|
friend constexpr bool
|
||||||
operator==(const _Iterator& __x, const _Iterator& __y)
|
operator==(const _Iterator& __x, const _Iterator& __y)
|
||||||
|
|||||||
@ -100,6 +100,21 @@ test04()
|
|||||||
static_assert(!requires { 0 | elements; });
|
static_assert(!requires { 0 | elements; });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
test05()
|
||||||
|
{
|
||||||
|
// LWG 3502
|
||||||
|
std::vector<int> vec = {42};
|
||||||
|
auto r1 = vec
|
||||||
|
| views::transform([](auto c) { return std::make_tuple(c, c); })
|
||||||
|
| views::keys;
|
||||||
|
VERIFY( ranges::equal(r1, (int[]){42}) );
|
||||||
|
|
||||||
|
std::tuple<int, int> a[] = {{1,2},{3,4}};
|
||||||
|
auto r2 = a | views::keys;
|
||||||
|
VERIFY( r2[0] == 1 && r2[1] == 3 );
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main()
|
main()
|
||||||
{
|
{
|
||||||
@ -107,4 +122,5 @@ main()
|
|||||||
test02();
|
test02();
|
||||||
test03();
|
test03();
|
||||||
test04();
|
test04();
|
||||||
|
test05();
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user