forked from OSchip/llvm-project
[libc++] Fix LWG3589 "The const lvalue reference overload of get for subrange..."
https://cplusplus.github.io/LWG/issue3589 Differential Revision: https://reviews.llvm.org/D117961
This commit is contained in:
parent
aefb2e134d
commit
6a56d5cc25
|
@ -130,7 +130,7 @@
|
|||
`3580 <https://wg21.link/LWG3580>`__,"``iota_view``'s ``iterator``'s binary ``operator+`` should be improved","October 2021","|Complete|","14.0","|ranges|"
|
||||
`3581 <https://wg21.link/LWG3581>`__,"The range constructor makes ``basic_string_view`` not trivially move constructible","October 2021","|Complete|","14.0","|ranges|"
|
||||
`3585 <https://wg21.link/LWG3585>`__,"``variant`` converting assignment with immovable alternative","October 2021","",""
|
||||
`3589 <https://wg21.link/LWG3589>`__,"The ``const`` lvalue reference overload of ``get`` for ``subrange`` does not constrain ``I`` to be ``copyable`` when ``N == 0``","October 2021","","","|ranges|"
|
||||
`3589 <https://wg21.link/LWG3589>`__,"The ``const`` lvalue reference overload of ``get`` for ``subrange`` does not constrain ``I`` to be ``copyable`` when ``N == 0``","October 2021","|Complete|","14.0","|ranges|"
|
||||
`3590 <https://wg21.link/LWG3590>`__,"``split_view::base() const &`` is overconstrained","October 2021","","","|ranges|"
|
||||
`3591 <https://wg21.link/LWG3591>`__,"``lazy_split_view<input_view>::inner-iterator::base() &&`` invalidates outer iterators","October 2021","","","|ranges|"
|
||||
`3592 <https://wg21.link/LWG3592>`__,"``lazy_split_view`` needs to check the simpleness of Pattern","October 2021","","","|ranges|"
|
||||
|
|
Can't render this file because it has a wrong number of fields in line 2.
|
|
@ -227,7 +227,7 @@ namespace ranges {
|
|||
-> subrange<iterator_t<_Range>, sentinel_t<_Range>, subrange_kind::sized>;
|
||||
|
||||
template<size_t _Index, class _Iter, class _Sent, subrange_kind _Kind>
|
||||
requires (_Index < 2)
|
||||
requires ((_Index == 0 && copyable<_Iter>) || _Index == 1)
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
constexpr auto get(const subrange<_Iter, _Sent, _Kind>& __subrange) {
|
||||
if constexpr (_Index == 0)
|
||||
|
|
|
@ -17,26 +17,75 @@
|
|||
#include <cassert>
|
||||
#include "test_macros.h"
|
||||
#include "test_iterators.h"
|
||||
#include "types.h"
|
||||
|
||||
template<size_t I, class S>
|
||||
concept GetInvocable = requires {
|
||||
concept HasGet = requires {
|
||||
std::get<I>(std::declval<S>());
|
||||
};
|
||||
|
||||
static_assert( GetInvocable<0, std::ranges::subrange<int*>>);
|
||||
static_assert( GetInvocable<1, std::ranges::subrange<int*>>);
|
||||
static_assert(!GetInvocable<2, std::ranges::subrange<int*>>);
|
||||
static_assert(!GetInvocable<3, std::ranges::subrange<int*>>);
|
||||
static_assert( HasGet<0, std::ranges::subrange<int*>>);
|
||||
static_assert( HasGet<1, std::ranges::subrange<int*>>);
|
||||
static_assert(!HasGet<2, std::ranges::subrange<int*>>);
|
||||
static_assert(!HasGet<3, std::ranges::subrange<int*>>);
|
||||
|
||||
constexpr bool test() {
|
||||
std::ranges::subrange<int*> a(globalBuff, globalBuff + 8, 8);
|
||||
assert(std::get<0>(a) == a.begin());
|
||||
assert(std::get<1>(a) == a.end());
|
||||
|
||||
assert(a.begin() == std::get<0>(std::move(a)));
|
||||
std::ranges::subrange<int*> b(globalBuff, globalBuff + 8, 8);
|
||||
assert(b.end() == std::get<1>(std::move(b)));
|
||||
{
|
||||
using It = int*;
|
||||
using Sent = sentinel_wrapper<int*>;
|
||||
int a[] = {1, 2, 3};
|
||||
using R = std::ranges::subrange<It, Sent, std::ranges::subrange_kind::unsized>;
|
||||
R r = R(It(a), Sent(It(a + 3)));
|
||||
ASSERT_SAME_TYPE(decltype(std::get<0>(r)), It);
|
||||
ASSERT_SAME_TYPE(decltype(std::get<1>(r)), Sent);
|
||||
ASSERT_SAME_TYPE(decltype(std::get<0>(static_cast<R&&>(r))), It);
|
||||
ASSERT_SAME_TYPE(decltype(std::get<1>(static_cast<R&&>(r))), Sent);
|
||||
ASSERT_SAME_TYPE(decltype(std::get<0>(static_cast<const R&>(r))), It);
|
||||
ASSERT_SAME_TYPE(decltype(std::get<1>(static_cast<const R&>(r))), Sent);
|
||||
ASSERT_SAME_TYPE(decltype(std::get<0>(static_cast<const R&&>(r))), It);
|
||||
ASSERT_SAME_TYPE(decltype(std::get<1>(static_cast<const R&&>(r))), Sent);
|
||||
assert(base(std::get<0>(r)) == a); // copy from It
|
||||
assert(base(base(std::get<1>(r))) == a + 3); // copy from Sent
|
||||
assert(base(std::get<0>(std::move(r))) == a); // copy from It
|
||||
assert(base(base(std::get<1>(std::move(r)))) == a + 3); // copy from Sent
|
||||
}
|
||||
{
|
||||
using It = int*;
|
||||
using Sent = sentinel_wrapper<int*>;
|
||||
int a[] = {1, 2, 3};
|
||||
using R = std::ranges::subrange<It, Sent, std::ranges::subrange_kind::sized>;
|
||||
R r = R(It(a), Sent(It(a + 3)), 3);
|
||||
ASSERT_SAME_TYPE(decltype(std::get<0>(r)), It);
|
||||
ASSERT_SAME_TYPE(decltype(std::get<1>(r)), Sent);
|
||||
ASSERT_SAME_TYPE(decltype(std::get<0>(static_cast<R&&>(r))), It);
|
||||
ASSERT_SAME_TYPE(decltype(std::get<1>(static_cast<R&&>(r))), Sent);
|
||||
ASSERT_SAME_TYPE(decltype(std::get<0>(static_cast<const R&>(r))), It);
|
||||
ASSERT_SAME_TYPE(decltype(std::get<1>(static_cast<const R&>(r))), Sent);
|
||||
ASSERT_SAME_TYPE(decltype(std::get<0>(static_cast<const R&&>(r))), It);
|
||||
ASSERT_SAME_TYPE(decltype(std::get<1>(static_cast<const R&&>(r))), Sent);
|
||||
assert(base(std::get<0>(r)) == a); // copy from It
|
||||
assert(base(base(std::get<1>(r))) == a + 3); // copy from Sent
|
||||
assert(base(std::get<0>(std::move(r))) == a); // copy from It
|
||||
assert(base(base(std::get<1>(std::move(r)))) == a + 3); // copy from Sent
|
||||
}
|
||||
{
|
||||
// Test the fix for LWG 3589.
|
||||
using It = cpp20_input_iterator<int*>;
|
||||
using Sent = sentinel_wrapper<It>;
|
||||
int a[] = {1, 2, 3};
|
||||
using R = std::ranges::subrange<It, Sent>;
|
||||
R r = R(It(a), Sent(It(a + 3)));
|
||||
static_assert(!HasGet<0, R&>);
|
||||
ASSERT_SAME_TYPE(decltype(std::get<1>(r)), Sent);
|
||||
ASSERT_SAME_TYPE(decltype(std::get<0>(static_cast<R&&>(r))), It);
|
||||
ASSERT_SAME_TYPE(decltype(std::get<1>(static_cast<R&&>(r))), Sent);
|
||||
static_assert(!HasGet<0, const R&>);
|
||||
ASSERT_SAME_TYPE(decltype(std::get<1>(static_cast<const R&>(r))), Sent);
|
||||
static_assert(!HasGet<0, const R&&>);
|
||||
ASSERT_SAME_TYPE(decltype(std::get<1>(static_cast<const R&&>(r))), Sent);
|
||||
assert(base(base(std::get<1>(r))) == a + 3); // copy from Sent
|
||||
assert(base(std::get<0>(std::move(r))) == a); // move from It
|
||||
assert(base(base(std::get<1>(std::move(r)))) == a + 3); // copy from Sent
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue