[libc++][ranges] Implement `indirectly_copyable{,_storable}`.

Also refactor tests for `indirectly_movable{,_storable}`.

Differential Revision: https://reviews.llvm.org/D118432
This commit is contained in:
Konstantin Varlamov 2022-02-02 13:27:28 -08:00
parent 712b31e2d4
commit e65d3760a3
43 changed files with 773 additions and 103 deletions

View File

@ -59,8 +59,8 @@ Section,Description,Dependencies,Assignee,Complete
`[projected] <https://wg21.link/projected>`_,`ranges::projected <https://llvm.org/D101277>`_,[iterator.concepts],Louis Dionne,✅
`[common.alg.req] <https://wg21.link/common.alg.req>`_: pt. 1,"| `indirectly_movable <https://llvm.org/D102639>`_
| `indirectly_movable_storable <https://llvm.org/D102639>`_
| indirectly_copyable
| indirectly_copyable_storable",[iterator.concepts],Zoe Carver,In progress
| `indirectly_copyable <https://llvm.org/D118432>`_
| `indirectly_copyable_storable <https://llvm.org/D118432>`_",[iterator.concepts],Zoe Carver and Konstantin Varlamov,✅
`[common.alg.req] <https://wg21.link/common.alg.req>`_: pt. 2,`indirectly_swappable <https://llvm.org/D105304>`_,"| [iterator.concepts]
| [iterator.cust.swap]",Zoe Carver,✅
`[common.alg.req] <https://wg21.link/common.alg.req>`_: pt. 3,`indirectly_comparable <https://llvm.org/D116268>`_,[projected],Nikolas Klauser,✅

1 Section Description Dependencies Assignee Complete
59
60
61
62
63
64
65
66

View File

@ -254,6 +254,22 @@ concept indirectly_movable_storable =
constructible_from<iter_value_t<_In>, iter_rvalue_reference_t<_In>> &&
assignable_from<iter_value_t<_In>&, iter_rvalue_reference_t<_In>>;
template<class _In, class _Out>
concept indirectly_copyable =
indirectly_readable<_In> &&
indirectly_writable<_Out, iter_reference_t<_In>>;
template<class _In, class _Out>
concept indirectly_copyable_storable =
indirectly_copyable<_In, _Out> &&
indirectly_writable<_Out, iter_value_t<_In>&> &&
indirectly_writable<_Out, const iter_value_t<_In>&> &&
indirectly_writable<_Out, iter_value_t<_In>&&> &&
indirectly_writable<_Out, const iter_value_t<_In>&&> &&
copyable<iter_value_t<_In>> &&
constructible_from<iter_value_t<_In>, iter_reference_t<_In>> &&
assignable_from<iter_value_t<_In>&, iter_reference_t<_In>>;
// Note: indirectly_swappable is located in iter_swap.h to prevent a dependency cycle
// (both iter_swap and indirectly_swappable require indirectly_readable).

View File

@ -136,6 +136,13 @@ template<class In, class Out>
template<class In, class Out>
concept indirectly_movable_storable = see below; // since C++20
// [alg.req.ind.copy], concept indirectly_copyable
template<class In, class Out>
concept indirectly_copyable = see below; // since C++20
template<class In, class Out>
concept indirectly_copyable_storable = see below; // since C++20
// [alg.req.ind.swap], concept indirectly_swappable
template<class I1, class I2 = I1>
concept indirectly_swappable = see below; // since C++20

View File

@ -34,6 +34,8 @@ static_assert(!std::sized_sentinel_for<iterator, reverse_iterator>);
static_assert(!std::sized_sentinel_for<iterator, const_reverse_iterator>);
static_assert( std::indirectly_movable<iterator, std::pair<int, int>*>);
static_assert(!std::indirectly_movable_storable<iterator, std::pair<int, int>*>);
static_assert( std::indirectly_copyable<iterator, std::pair<int, int>*>);
static_assert(!std::indirectly_copyable_storable<iterator, std::pair<int, int>*>);
static_assert(!std::indirectly_swappable<iterator, iterator>);
static_assert(std::bidirectional_iterator<const_iterator>);

View File

@ -34,6 +34,8 @@ static_assert(!std::sized_sentinel_for<iterator, reverse_iterator>);
static_assert(!std::sized_sentinel_for<iterator, const_reverse_iterator>);
static_assert( std::indirectly_movable<iterator, std::pair<int, int>*>);
static_assert(!std::indirectly_movable_storable<iterator, std::pair<int, int>*>);
static_assert( std::indirectly_copyable<iterator, std::pair<int, int>*>);
static_assert(!std::indirectly_copyable_storable<iterator, std::pair<int, int>*>);
static_assert(!std::indirectly_swappable<iterator, iterator>);
static_assert(std::bidirectional_iterator<const_iterator>);

View File

@ -34,6 +34,8 @@ static_assert(!std::sized_sentinel_for<iterator, reverse_iterator>);
static_assert(!std::sized_sentinel_for<iterator, const_reverse_iterator>);
static_assert(std::indirectly_movable<iterator, int*>);
static_assert(std::indirectly_movable_storable<iterator, int*>);
static_assert(std::indirectly_copyable<iterator, int*>);
static_assert(std::indirectly_copyable_storable<iterator, int*>);
static_assert(!std::indirectly_swappable<iterator, iterator>);
static_assert(std::bidirectional_iterator<const_iterator>);

View File

@ -34,6 +34,8 @@ static_assert(!std::sized_sentinel_for<iterator, reverse_iterator>);
static_assert(!std::sized_sentinel_for<iterator, const_reverse_iterator>);
static_assert(std::indirectly_movable<iterator, int*>);
static_assert(std::indirectly_movable_storable<iterator, int*>);
static_assert(std::indirectly_copyable<iterator, int*>);
static_assert(std::indirectly_copyable_storable<iterator, int*>);
static_assert(!std::indirectly_swappable<iterator, iterator>);
static_assert(std::bidirectional_iterator<const_iterator>);

View File

@ -38,6 +38,14 @@ static_assert( std::indirectly_movable<iterator, reverse_iterator>);
static_assert( std::indirectly_movable_storable<iterator, reverse_iterator>);
static_assert(!std::indirectly_movable<iterator, const_reverse_iterator>);
static_assert(!std::indirectly_movable_storable<iterator, const_reverse_iterator>);
static_assert( std::indirectly_copyable<iterator, iterator>);
static_assert( std::indirectly_copyable_storable<iterator, iterator>);
static_assert(!std::indirectly_copyable<iterator, const_iterator>);
static_assert(!std::indirectly_copyable_storable<iterator, const_iterator>);
static_assert( std::indirectly_copyable<iterator, reverse_iterator>);
static_assert( std::indirectly_copyable_storable<iterator, reverse_iterator>);
static_assert(!std::indirectly_copyable<iterator, const_reverse_iterator>);
static_assert(!std::indirectly_copyable_storable<iterator, const_reverse_iterator>);
static_assert( std::indirectly_swappable<iterator, iterator>);
static_assert(std::contiguous_iterator<const_iterator>);
@ -58,4 +66,12 @@ static_assert( std::indirectly_movable<const_iterator, reverse_iterator>);
static_assert( std::indirectly_movable_storable<const_iterator, reverse_iterator>);
static_assert(!std::indirectly_movable<const_iterator, const_reverse_iterator>);
static_assert(!std::indirectly_movable_storable<const_iterator, const_reverse_iterator>);
static_assert( std::indirectly_copyable<const_iterator, iterator>);
static_assert( std::indirectly_copyable_storable<const_iterator, iterator>);
static_assert(!std::indirectly_copyable<const_iterator, const_iterator>);
static_assert(!std::indirectly_copyable_storable<const_iterator, const_iterator>);
static_assert( std::indirectly_copyable<const_iterator, reverse_iterator>);
static_assert( std::indirectly_copyable_storable<const_iterator, reverse_iterator>);
static_assert(!std::indirectly_copyable<const_iterator, const_reverse_iterator>);
static_assert(!std::indirectly_copyable_storable<const_iterator, const_reverse_iterator>);
static_assert(!std::indirectly_swappable<const_iterator, const_iterator>);

View File

@ -40,6 +40,14 @@ static_assert( std::indirectly_movable<iterator, reverse_iterator>);
static_assert( std::indirectly_movable_storable<iterator, reverse_iterator>);
static_assert(!std::indirectly_movable<iterator, const_reverse_iterator>);
static_assert(!std::indirectly_movable_storable<iterator, const_reverse_iterator>);
static_assert( std::indirectly_copyable<iterator, iterator>);
static_assert( std::indirectly_copyable_storable<iterator, iterator>);
static_assert(!std::indirectly_copyable<iterator, const_iterator>);
static_assert(!std::indirectly_copyable_storable<iterator, const_iterator>);
static_assert( std::indirectly_copyable<iterator, reverse_iterator>);
static_assert( std::indirectly_copyable_storable<iterator, reverse_iterator>);
static_assert(!std::indirectly_copyable<iterator, const_reverse_iterator>);
static_assert(!std::indirectly_copyable_storable<iterator, const_reverse_iterator>);
static_assert(std::indirectly_swappable<iterator, iterator>);
static_assert(std::random_access_iterator<const_iterator>);
@ -61,4 +69,12 @@ static_assert( std::indirectly_movable<const_iterator, reverse_iterator>);
static_assert( std::indirectly_movable_storable<const_iterator, reverse_iterator>);
static_assert(!std::indirectly_movable<const_iterator, const_reverse_iterator>);
static_assert(!std::indirectly_movable_storable<const_iterator, const_reverse_iterator>);
static_assert( std::indirectly_copyable<const_iterator, iterator>);
static_assert( std::indirectly_copyable_storable<const_iterator, iterator>);
static_assert(!std::indirectly_copyable<const_iterator, const_iterator>);
static_assert(!std::indirectly_copyable_storable<const_iterator, const_iterator>);
static_assert( std::indirectly_copyable<const_iterator, reverse_iterator>);
static_assert( std::indirectly_copyable_storable<const_iterator, reverse_iterator>);
static_assert(!std::indirectly_copyable<const_iterator, const_reverse_iterator>);
static_assert(!std::indirectly_copyable_storable<const_iterator, const_reverse_iterator>);
static_assert(!std::indirectly_swappable<const_iterator, const_iterator>);

View File

@ -30,6 +30,10 @@ static_assert( std::indirectly_movable<iterator, iterator>);
static_assert( std::indirectly_movable_storable<iterator, iterator>);
static_assert(!std::indirectly_movable<iterator, const_iterator>);
static_assert(!std::indirectly_movable_storable<iterator, const_iterator>);
static_assert( std::indirectly_copyable<iterator, iterator>);
static_assert( std::indirectly_copyable_storable<iterator, iterator>);
static_assert(!std::indirectly_copyable<iterator, const_iterator>);
static_assert(!std::indirectly_copyable_storable<iterator, const_iterator>);
static_assert(std::indirectly_swappable<iterator, iterator>);
static_assert(std::forward_iterator<const_iterator>);
@ -43,4 +47,8 @@ static_assert( std::indirectly_movable<const_iterator, iterator>);
static_assert( std::indirectly_movable_storable<const_iterator, iterator>);
static_assert(!std::indirectly_movable<const_iterator, const_iterator>);
static_assert(!std::indirectly_movable_storable<const_iterator, const_iterator>);
static_assert( std::indirectly_copyable<const_iterator, iterator>);
static_assert( std::indirectly_copyable_storable<const_iterator, iterator>);
static_assert(!std::indirectly_copyable<const_iterator, const_iterator>);
static_assert(!std::indirectly_copyable_storable<const_iterator, const_iterator>);
static_assert(!std::indirectly_swappable<const_iterator, const_iterator>);

View File

@ -40,6 +40,14 @@ static_assert( std::indirectly_movable<iterator, reverse_iterator>);
static_assert( std::indirectly_movable_storable<iterator, reverse_iterator>);
static_assert(!std::indirectly_movable<iterator, const_reverse_iterator>);
static_assert(!std::indirectly_movable_storable<iterator, const_reverse_iterator>);
static_assert( std::indirectly_copyable<iterator, iterator>);
static_assert( std::indirectly_copyable_storable<iterator, iterator>);
static_assert(!std::indirectly_copyable<iterator, const_iterator>);
static_assert(!std::indirectly_copyable_storable<iterator, const_iterator>);
static_assert( std::indirectly_copyable<iterator, reverse_iterator>);
static_assert( std::indirectly_copyable_storable<iterator, reverse_iterator>);
static_assert(!std::indirectly_copyable<iterator, const_reverse_iterator>);
static_assert(!std::indirectly_copyable_storable<iterator, const_reverse_iterator>);
static_assert(std::indirectly_swappable<iterator, iterator>);
static_assert(std::bidirectional_iterator<const_iterator>);
@ -61,4 +69,12 @@ static_assert( std::indirectly_movable<const_iterator, reverse_iterator>);
static_assert( std::indirectly_movable_storable<const_iterator, reverse_iterator>);
static_assert(!std::indirectly_movable<const_iterator, const_reverse_iterator>);
static_assert(!std::indirectly_movable_storable<const_iterator, const_reverse_iterator>);
static_assert( std::indirectly_copyable<const_iterator, iterator>);
static_assert( std::indirectly_copyable_storable<const_iterator, iterator>);
static_assert(!std::indirectly_copyable<const_iterator, const_iterator>);
static_assert(!std::indirectly_copyable_storable<const_iterator, const_iterator>);
static_assert( std::indirectly_copyable<const_iterator, reverse_iterator>);
static_assert( std::indirectly_copyable_storable<const_iterator, reverse_iterator>);
static_assert(!std::indirectly_copyable<const_iterator, const_reverse_iterator>);
static_assert(!std::indirectly_copyable_storable<const_iterator, const_reverse_iterator>);
static_assert(!std::indirectly_swappable<const_iterator, const_iterator>);

View File

@ -36,6 +36,8 @@ static_assert(!std::sized_sentinel_for<iterator, reverse_iterator>);
static_assert(!std::sized_sentinel_for<iterator, const_reverse_iterator>);
static_assert(std::indirectly_movable<iterator, bool*>);
static_assert(std::indirectly_movable_storable<iterator, bool*>);
static_assert(std::indirectly_copyable<iterator, bool*>);
static_assert(std::indirectly_copyable_storable<iterator, bool*>);
static_assert(std::indirectly_swappable<iterator, iterator>);
static_assert( std::random_access_iterator<const_iterator>);

View File

@ -41,6 +41,14 @@ static_assert( std::indirectly_movable<iterator, reverse_iterator>);
static_assert( std::indirectly_movable_storable<iterator, reverse_iterator>);
static_assert(!std::indirectly_movable<iterator, const_reverse_iterator>);
static_assert(!std::indirectly_movable_storable<iterator, const_reverse_iterator>);
static_assert( std::indirectly_copyable<iterator, iterator>);
static_assert( std::indirectly_copyable_storable<iterator, iterator>);
static_assert(!std::indirectly_copyable<iterator, const_iterator>);
static_assert(!std::indirectly_copyable_storable<iterator, const_iterator>);
static_assert( std::indirectly_copyable<iterator, reverse_iterator>);
static_assert( std::indirectly_copyable_storable<iterator, reverse_iterator>);
static_assert(!std::indirectly_copyable<iterator, const_reverse_iterator>);
static_assert(!std::indirectly_copyable_storable<iterator, const_reverse_iterator>);
static_assert(std::indirectly_swappable<iterator, iterator>);
static_assert( std::contiguous_iterator<const_iterator>);
@ -63,4 +71,12 @@ static_assert( std::indirectly_movable<const_iterator, reverse_iterator>);
static_assert( std::indirectly_movable_storable<const_iterator, reverse_iterator>);
static_assert(!std::indirectly_movable<const_iterator, const_reverse_iterator>);
static_assert(!std::indirectly_movable_storable<const_iterator, const_reverse_iterator>);
static_assert( std::indirectly_copyable<const_iterator, iterator>);
static_assert( std::indirectly_copyable_storable<const_iterator, iterator>);
static_assert(!std::indirectly_copyable<const_iterator, const_iterator>);
static_assert(!std::indirectly_copyable_storable<const_iterator, const_iterator>);
static_assert( std::indirectly_copyable<const_iterator, reverse_iterator>);
static_assert( std::indirectly_copyable_storable<const_iterator, reverse_iterator>);
static_assert(!std::indirectly_copyable<const_iterator, const_reverse_iterator>);
static_assert(!std::indirectly_copyable_storable<const_iterator, const_reverse_iterator>);
static_assert(!std::indirectly_swappable<const_iterator, const_iterator>);

View File

@ -32,6 +32,8 @@ static_assert(!std::sized_sentinel_for<iterator, iterator>);
static_assert(!std::sized_sentinel_for<iterator, const_iterator>);
static_assert(std::indirectly_movable<iterator, std::pair<int, int>*>);
static_assert(!std::indirectly_movable_storable<iterator, std::pair<int, int>*>);
static_assert(std::indirectly_copyable<iterator, std::pair<int, int>*>);
static_assert(!std::indirectly_copyable_storable<iterator, std::pair<int, int>*>);
static_assert(!std::indirectly_swappable<iterator, iterator>);
static_assert(std::forward_iterator<const_iterator>);
@ -43,6 +45,8 @@ static_assert(!std::sized_sentinel_for<const_iterator, iterator>);
static_assert(!std::sized_sentinel_for<const_iterator, const_iterator>);
static_assert(std::indirectly_movable<const_iterator, std::pair<int, int>*>);
static_assert(!std::indirectly_movable_storable<const_iterator, std::pair<int, int>*>);
static_assert(std::indirectly_copyable<const_iterator, std::pair<int, int>*>);
static_assert(!std::indirectly_copyable_storable<const_iterator, std::pair<int, int>*>);
static_assert(!std::indirectly_swappable<const_iterator, const_iterator>);
static_assert(std::forward_iterator<local_iterator>);
@ -54,6 +58,8 @@ static_assert(!std::sized_sentinel_for<local_iterator, local_iterator>);
static_assert(!std::sized_sentinel_for<local_iterator, const_local_iterator>);
static_assert(std::indirectly_movable<local_iterator, std::pair<int, int>*>);
static_assert(!std::indirectly_movable_storable<local_iterator, std::pair<int, int>*>);
static_assert(std::indirectly_copyable<local_iterator, std::pair<int, int>*>);
static_assert(!std::indirectly_copyable_storable<local_iterator, std::pair<int, int>*>);
static_assert(!std::indirectly_swappable<local_iterator, local_iterator>);
static_assert(std::forward_iterator<const_local_iterator>);
@ -65,4 +71,6 @@ static_assert(!std::sized_sentinel_for<const_local_iterator, local_iterator>);
static_assert(!std::sized_sentinel_for<const_local_iterator, const_local_iterator>);
static_assert(std::indirectly_movable<const_local_iterator, std::pair<int, int>*>);
static_assert(!std::indirectly_movable_storable<const_local_iterator, std::pair<int, int>*>);
static_assert(std::indirectly_copyable<const_local_iterator, std::pair<int, int>*>);
static_assert(!std::indirectly_copyable_storable<const_local_iterator, std::pair<int, int>*>);
static_assert(!std::indirectly_swappable<const_local_iterator, const_local_iterator>);

View File

@ -32,6 +32,8 @@ static_assert(!std::sized_sentinel_for<iterator, iterator>);
static_assert(!std::sized_sentinel_for<iterator, const_iterator>);
static_assert(std::indirectly_movable<iterator, std::pair<int, int>*>);
static_assert(!std::indirectly_movable_storable<iterator, std::pair<int, int>*>);
static_assert(std::indirectly_copyable<iterator, std::pair<int, int>*>);
static_assert(!std::indirectly_copyable_storable<iterator, std::pair<int, int>*>);
static_assert(!std::indirectly_swappable<iterator, iterator>);
static_assert(std::forward_iterator<const_iterator>);
@ -43,6 +45,8 @@ static_assert(!std::sized_sentinel_for<const_iterator, iterator>);
static_assert(!std::sized_sentinel_for<const_iterator, const_iterator>);
static_assert(std::indirectly_movable<const_iterator, std::pair<int, int>*>);
static_assert(!std::indirectly_movable_storable<const_iterator, std::pair<int, int>*>);
static_assert(std::indirectly_copyable<const_iterator, std::pair<int, int>*>);
static_assert(!std::indirectly_copyable_storable<const_iterator, std::pair<int, int>*>);
static_assert(!std::indirectly_swappable<const_iterator, const_iterator>);
static_assert(std::forward_iterator<local_iterator>);
@ -54,6 +58,8 @@ static_assert(!std::sized_sentinel_for<local_iterator, local_iterator>);
static_assert(!std::sized_sentinel_for<local_iterator, const_local_iterator>);
static_assert(std::indirectly_movable<local_iterator, std::pair<int, int>*>);
static_assert(!std::indirectly_movable_storable<local_iterator, std::pair<int, int>*>);
static_assert(std::indirectly_copyable<local_iterator, std::pair<int, int>*>);
static_assert(!std::indirectly_copyable_storable<local_iterator, std::pair<int, int>*>);
static_assert(!std::indirectly_swappable<local_iterator, local_iterator>);
static_assert(std::forward_iterator<const_local_iterator>);
@ -65,4 +71,6 @@ static_assert(!std::sized_sentinel_for<const_local_iterator, local_iterator>);
static_assert(!std::sized_sentinel_for<const_local_iterator, const_local_iterator>);
static_assert(std::indirectly_movable<const_local_iterator, std::pair<int, int>*>);
static_assert(!std::indirectly_movable_storable<const_local_iterator, std::pair<int, int>*>);
static_assert(std::indirectly_copyable<const_local_iterator, std::pair<int, int>*>);
static_assert(!std::indirectly_copyable_storable<const_local_iterator, std::pair<int, int>*>);
static_assert(!std::indirectly_swappable<const_local_iterator, const_local_iterator>);

View File

@ -32,6 +32,8 @@ static_assert(!std::sized_sentinel_for<iterator, iterator>);
static_assert(!std::sized_sentinel_for<iterator, const_iterator>);
static_assert(std::indirectly_movable<iterator, int*>);
static_assert(std::indirectly_movable_storable<iterator, int*>);
static_assert(std::indirectly_copyable<iterator, int*>);
static_assert(std::indirectly_copyable_storable<iterator, int*>);
static_assert(!std::indirectly_swappable<iterator, iterator>);
static_assert(std::forward_iterator<const_iterator>);
@ -43,6 +45,8 @@ static_assert(!std::sized_sentinel_for<const_iterator, iterator>);
static_assert(!std::sized_sentinel_for<const_iterator, const_iterator>);
static_assert(std::indirectly_movable<const_iterator, int*>);
static_assert(std::indirectly_movable_storable<const_iterator, int*>);
static_assert(std::indirectly_copyable<const_iterator, int*>);
static_assert(std::indirectly_copyable_storable<const_iterator, int*>);
static_assert(!std::indirectly_swappable<const_iterator, const_iterator>);
static_assert(std::forward_iterator<local_iterator>);
@ -54,6 +58,8 @@ static_assert(!std::sized_sentinel_for<local_iterator, local_iterator>);
static_assert(!std::sized_sentinel_for<local_iterator, const_local_iterator>);
static_assert(std::indirectly_movable<local_iterator, int*>);
static_assert(std::indirectly_movable_storable<local_iterator, int*>);
static_assert(std::indirectly_copyable<local_iterator, int*>);
static_assert(std::indirectly_copyable_storable<local_iterator, int*>);
static_assert(!std::indirectly_swappable<local_iterator, local_iterator>);
static_assert(std::forward_iterator<const_local_iterator>);
@ -65,4 +71,6 @@ static_assert(!std::sized_sentinel_for<const_local_iterator, local_iterator>);
static_assert(!std::sized_sentinel_for<const_local_iterator, const_local_iterator>);
static_assert(std::indirectly_movable<const_local_iterator, int*>);
static_assert(std::indirectly_movable_storable<const_local_iterator, int*>);
static_assert(std::indirectly_copyable<const_local_iterator, int*>);
static_assert(std::indirectly_copyable_storable<const_local_iterator, int*>);
static_assert(!std::indirectly_swappable<const_local_iterator, const_local_iterator>);

View File

@ -32,6 +32,8 @@ static_assert(!std::sized_sentinel_for<iterator, iterator>);
static_assert(!std::sized_sentinel_for<iterator, const_iterator>);
static_assert(std::indirectly_movable<iterator, int*>);
static_assert(std::indirectly_movable_storable<iterator, int*>);
static_assert(std::indirectly_copyable<iterator, int*>);
static_assert(std::indirectly_copyable_storable<iterator, int*>);
static_assert(!std::indirectly_swappable<iterator, iterator>);
static_assert(std::forward_iterator<const_iterator>);
@ -43,6 +45,8 @@ static_assert(!std::sized_sentinel_for<const_iterator, iterator>);
static_assert(!std::sized_sentinel_for<const_iterator, const_iterator>);
static_assert(std::indirectly_movable<const_iterator, int*>);
static_assert(std::indirectly_movable_storable<const_iterator, int*>);
static_assert(std::indirectly_copyable<const_iterator, int*>);
static_assert(std::indirectly_copyable_storable<const_iterator, int*>);
static_assert(!std::indirectly_swappable<const_iterator, const_iterator>);
static_assert(std::forward_iterator<local_iterator>);
@ -53,6 +57,8 @@ static_assert(!std::sized_sentinel_for<local_iterator, local_iterator>);
static_assert(!std::sized_sentinel_for<local_iterator, const_local_iterator>);
static_assert(std::indirectly_movable<local_iterator, int*>);
static_assert(std::indirectly_movable_storable<local_iterator, int*>);
static_assert(std::indirectly_copyable<local_iterator, int*>);
static_assert(std::indirectly_copyable_storable<local_iterator, int*>);
static_assert(!std::indirectly_swappable<local_iterator, local_iterator>);
static_assert(std::forward_iterator<const_local_iterator>);
@ -64,4 +70,6 @@ static_assert(!std::sized_sentinel_for<const_local_iterator, local_iterator>);
static_assert(!std::sized_sentinel_for<const_local_iterator, const_local_iterator>);
static_assert(std::indirectly_movable<const_local_iterator, int*>);
static_assert(std::indirectly_movable_storable<const_local_iterator, int*>);
static_assert(std::indirectly_copyable<const_local_iterator, int*>);
static_assert(std::indirectly_copyable_storable<const_local_iterator, int*>);
static_assert(!std::indirectly_swappable<const_local_iterator, const_local_iterator>);

View File

@ -29,4 +29,6 @@ static_assert(std::sized_sentinel_for<iterator, iterator>);
static_assert(!std::sized_sentinel_for<iterator, reverse_iterator>);
static_assert(std::indirectly_movable<iterator, int*>);
static_assert(std::indirectly_movable_storable<iterator, int*>);
static_assert(std::indirectly_copyable<iterator, int*>);
static_assert(std::indirectly_copyable_storable<iterator, int*>);
static_assert(std::indirectly_swappable<iterator, iterator>);

View File

@ -25,6 +25,8 @@ static_assert(std::sentinel_for<fs::directory_iterator, fs::directory_iterator>)
static_assert(!std::sized_sentinel_for<fs::directory_iterator, fs::directory_iterator>);
static_assert(!std::indirectly_movable<fs::directory_iterator, fs::directory_iterator>);
static_assert(!std::indirectly_movable_storable<fs::directory_iterator, fs::directory_iterator>);
static_assert(!std::indirectly_copyable<fs::directory_iterator, fs::directory_iterator>);
static_assert(!std::indirectly_copyable_storable<fs::directory_iterator, fs::directory_iterator>);
static_assert(!std::indirectly_swappable<fs::directory_iterator, fs::directory_iterator>);
static_assert(std::input_iterator<fs::recursive_directory_iterator>);
@ -35,4 +37,6 @@ static_assert(std::sentinel_for<fs::recursive_directory_iterator, fs::recursive_
static_assert(!std::sized_sentinel_for<fs::recursive_directory_iterator, fs::recursive_directory_iterator>);
static_assert(!std::indirectly_movable<fs::recursive_directory_iterator, fs::recursive_directory_iterator>);
static_assert(!std::indirectly_movable_storable<fs::recursive_directory_iterator, fs::recursive_directory_iterator>);
static_assert(!std::indirectly_copyable<fs::recursive_directory_iterator, fs::recursive_directory_iterator>);
static_assert(!std::indirectly_copyable_storable<fs::recursive_directory_iterator, fs::recursive_directory_iterator>);
static_assert(!std::indirectly_swappable<fs::recursive_directory_iterator, fs::recursive_directory_iterator>);

View File

@ -0,0 +1,81 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-no-concepts
// template<class In, class Out>
// concept indirectly_copyable;
#include <iterator>
#include "MoveOnly.h"
#include "test_macros.h"
struct CopyOnly {
CopyOnly() = default;
CopyOnly(CopyOnly const&) = default;
CopyOnly& operator=(CopyOnly const&) = default;
CopyOnly(CopyOnly&&) = delete;
CopyOnly& operator=(CopyOnly&&) = delete;
};
// Can copy the underlying objects between pointers.
static_assert( std::indirectly_copyable<int*, int*>);
static_assert( std::indirectly_copyable<const int*, int *>);
// Can't copy if the output pointer is const.
static_assert(!std::indirectly_copyable<int*, const int *>);
static_assert(!std::indirectly_copyable<const int*, const int *>);
// Can copy from a pointer into an array but arrays aren't considered indirectly copyable-from.
static_assert( std::indirectly_copyable<int*, int[2]>);
static_assert(!std::indirectly_copyable<int[2], int*>);
static_assert(!std::indirectly_copyable<int[2], int[2]>);
static_assert(!std::indirectly_copyable<int(&)[2], int(&)[2]>);
// Can't copy between non-pointer types.
static_assert(!std::indirectly_copyable<int*, int>);
static_assert(!std::indirectly_copyable<int, int*>);
static_assert(!std::indirectly_copyable<int, int>);
// Check some less common types.
static_assert(!std::indirectly_movable<void*, void*>);
static_assert(!std::indirectly_movable<int*, void*>);
static_assert(!std::indirectly_movable<int(), int()>);
static_assert(!std::indirectly_movable<int*, int()>);
static_assert(!std::indirectly_movable<void, void>);
// Can't copy move-only objects.
static_assert(!std::indirectly_copyable<MoveOnly*, MoveOnly*>);
static_assert(!std::indirectly_copyable<MoveOnly*, const MoveOnly*>);
static_assert(!std::indirectly_copyable<const MoveOnly*, MoveOnly*>);
static_assert(!std::indirectly_copyable<const MoveOnly*, const MoveOnly*>);
// Can copy copy-only objects.
static_assert( std::indirectly_copyable<CopyOnly*, CopyOnly*>);
static_assert(!std::indirectly_copyable<CopyOnly*, const CopyOnly*>);
static_assert( std::indirectly_copyable<const CopyOnly*, CopyOnly*>);
static_assert(!std::indirectly_copyable<const CopyOnly*, const CopyOnly*>);
template<class T>
struct PointerTo {
using value_type = T;
T& operator*() const;
};
// Can copy through a dereferenceable class.
static_assert( std::indirectly_copyable<int*, PointerTo<int>>);
static_assert(!std::indirectly_copyable<int*, PointerTo<const int>>);
static_assert( std::indirectly_copyable<PointerTo<int>, PointerTo<int>>);
static_assert(!std::indirectly_copyable<PointerTo<int>, PointerTo<const int>>);
static_assert( std::indirectly_copyable<CopyOnly*, PointerTo<CopyOnly>>);
static_assert( std::indirectly_copyable<PointerTo<CopyOnly>, CopyOnly*>);
static_assert( std::indirectly_copyable<PointerTo<CopyOnly>, PointerTo<CopyOnly>>);

View File

@ -0,0 +1,28 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-no-concepts
// template<class In, class Out>
// concept indirectly_copyable;
#include <iterator>
template<std::indirectly_readable I, class O>
constexpr bool indirectly_copyable_subsumption() {
return false;
}
template<class I, class O>
requires std::indirectly_copyable<I, O>
constexpr bool indirectly_copyable_subsumption() {
return true;
}
static_assert(indirectly_copyable_subsumption<int*, int*>());

View File

@ -0,0 +1,305 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-no-concepts
// template<class In, class Out>
// concept indirectly_copyable_storable;
#include <iterator>
#include "MoveOnly.h"
#include "test_macros.h"
struct CopyOnly {
CopyOnly(CopyOnly&&) = delete;
CopyOnly(CopyOnly const&) = default;
CopyOnly& operator=(CopyOnly&&) = delete;
CopyOnly& operator=(CopyOnly const&) = default;
CopyOnly() = default;
};
template<class T>
struct PointerTo {
using value_type = T;
T& operator*() const;
};
// Copying the underlying object between pointers (or dereferenceable classes) works. This is a non-exhaustive check
// because this functionality comes from `indirectly_copyable`.
static_assert( std::indirectly_copyable_storable<int*, int*>);
static_assert( std::indirectly_copyable_storable<const int*, int*>);
static_assert(!std::indirectly_copyable_storable<int*, const int*>);
static_assert(!std::indirectly_copyable_storable<const int*, const int*>);
static_assert( std::indirectly_copyable_storable<int*, int[2]>);
static_assert(!std::indirectly_copyable_storable<int[2], int*>);
static_assert(!std::indirectly_copyable_storable<MoveOnly*, MoveOnly*>);
static_assert(!std::indirectly_copyable_storable<PointerTo<MoveOnly>, PointerTo<MoveOnly>>);
// `indirectly_copyable_storable` requires the type to be `copyable`, which in turns requires it to be `movable`.
static_assert(!std::indirectly_copyable_storable<CopyOnly*, CopyOnly*>);
static_assert(!std::indirectly_copyable_storable<PointerTo<CopyOnly>, PointerTo<CopyOnly>>);
// The dereference operator returns a different type from `value_type` and the reference type cannot be assigned from a
// non-const lvalue of `ValueType` (but all other forms of assignment from `ValueType` work).
struct NoLvalueAssignment {
struct ValueType;
struct ReferenceType {
ReferenceType& operator=(ValueType const&);
ReferenceType& operator=(ValueType&) = delete;
ReferenceType& operator=(ValueType&&);
ReferenceType& operator=(ValueType const&&);
};
struct ValueType {
operator ReferenceType&() const;
};
using value_type = ValueType;
ReferenceType& operator*() const;
};
static_assert( std::indirectly_writable<NoLvalueAssignment, std::iter_reference_t<NoLvalueAssignment>>);
static_assert(!std::indirectly_writable<NoLvalueAssignment, std::iter_value_t<NoLvalueAssignment>&>);
static_assert( std::indirectly_writable<NoLvalueAssignment, const std::iter_value_t<NoLvalueAssignment>&>);
static_assert( std::indirectly_writable<NoLvalueAssignment, std::iter_value_t<NoLvalueAssignment>&&>);
static_assert( std::indirectly_writable<NoLvalueAssignment, const std::iter_value_t<NoLvalueAssignment>&&>);
static_assert(!std::indirectly_copyable_storable<NoLvalueAssignment, NoLvalueAssignment>);
// The dereference operator returns a different type from `value_type` and the reference type cannot be assigned from a
// const lvalue of `ValueType` (but all other forms of assignment from `ValueType` work).
struct NoConstLvalueAssignment {
struct ValueType;
struct ReferenceType {
ReferenceType& operator=(ValueType const&) = delete;
ReferenceType& operator=(ValueType&);
ReferenceType& operator=(ValueType&&);
ReferenceType& operator=(ValueType const&&);
};
struct ValueType {
operator ReferenceType&() const;
};
using value_type = ValueType;
ReferenceType& operator*() const;
};
static_assert( std::indirectly_writable<NoConstLvalueAssignment, std::iter_reference_t<NoConstLvalueAssignment>>);
static_assert( std::indirectly_writable<NoConstLvalueAssignment, std::iter_value_t<NoConstLvalueAssignment>&>);
static_assert(!std::indirectly_writable<NoConstLvalueAssignment, const std::iter_value_t<NoConstLvalueAssignment>&>);
static_assert( std::indirectly_writable<NoConstLvalueAssignment, std::iter_value_t<NoConstLvalueAssignment>&&>);
static_assert( std::indirectly_writable<NoConstLvalueAssignment, const std::iter_value_t<NoConstLvalueAssignment>&&>);
static_assert(!std::indirectly_copyable_storable<NoConstLvalueAssignment, NoConstLvalueAssignment>);
// The dereference operator returns a different type from `value_type` and the reference type cannot be assigned from a
// non-const rvalue of `ValueType` (but all other forms of assignment from `ValueType` work).
struct NoRvalueAssignment {
struct ValueType;
struct ReferenceType {
ReferenceType& operator=(ValueType const&);
ReferenceType& operator=(ValueType&);
ReferenceType& operator=(ValueType&&) = delete;
ReferenceType& operator=(ValueType const&&);
};
struct ValueType {
operator ReferenceType&() const;
};
using value_type = ValueType;
ReferenceType& operator*() const;
};
static_assert( std::indirectly_writable<NoRvalueAssignment, std::iter_reference_t<NoRvalueAssignment>>);
static_assert( std::indirectly_writable<NoRvalueAssignment, std::iter_value_t<NoRvalueAssignment>&>);
static_assert( std::indirectly_writable<NoRvalueAssignment, const std::iter_value_t<NoRvalueAssignment>&>);
static_assert(!std::indirectly_writable<NoRvalueAssignment, std::iter_value_t<NoRvalueAssignment>&&>);
static_assert( std::indirectly_writable<NoRvalueAssignment, const std::iter_value_t<NoRvalueAssignment>&&>);
static_assert(!std::indirectly_copyable_storable<NoRvalueAssignment, NoRvalueAssignment>);
// The dereference operator returns a different type from `value_type` and the reference type cannot be assigned from a
// const rvalue of `ValueType` (but all other forms of assignment from `ValueType` work).
struct NoConstRvalueAssignment {
struct ValueType;
struct ReferenceType {
ReferenceType& operator=(ValueType const&);
ReferenceType& operator=(ValueType&);
ReferenceType& operator=(ValueType&&);
ReferenceType& operator=(ValueType const&&) = delete;
};
struct ValueType {
operator ReferenceType&() const;
};
using value_type = ValueType;
ReferenceType& operator*() const;
};
static_assert( std::indirectly_writable<NoConstRvalueAssignment, std::iter_reference_t<NoConstRvalueAssignment>>);
static_assert( std::indirectly_writable<NoConstRvalueAssignment, std::iter_value_t<NoConstRvalueAssignment>&>);
static_assert( std::indirectly_writable<NoConstRvalueAssignment, const std::iter_value_t<NoConstRvalueAssignment>&>);
static_assert( std::indirectly_writable<NoConstRvalueAssignment, std::iter_value_t<NoConstRvalueAssignment>&&>);
static_assert(!std::indirectly_writable<NoConstRvalueAssignment, const std::iter_value_t<NoConstRvalueAssignment>&&>);
static_assert(!std::indirectly_copyable_storable<NoConstRvalueAssignment, NoConstRvalueAssignment>);
struct DeletedCopyCtor {
DeletedCopyCtor(DeletedCopyCtor const&) = delete;
DeletedCopyCtor& operator=(DeletedCopyCtor const&) = default;
};
struct DeletedNonconstCopyCtor {
DeletedNonconstCopyCtor(DeletedNonconstCopyCtor const&) = default;
DeletedNonconstCopyCtor(DeletedNonconstCopyCtor&) = delete;
DeletedNonconstCopyCtor& operator=(DeletedNonconstCopyCtor const&) = default;
};
struct DeletedMoveCtor {
DeletedMoveCtor(DeletedMoveCtor&&) = delete;
DeletedMoveCtor& operator=(DeletedMoveCtor&&) = default;
};
struct DeletedConstMoveCtor {
DeletedConstMoveCtor(DeletedConstMoveCtor&&) = default;
DeletedConstMoveCtor(DeletedConstMoveCtor const&&) = delete;
DeletedConstMoveCtor& operator=(DeletedConstMoveCtor&&) = default;
};
struct DeletedCopyAssignment {
DeletedCopyAssignment(DeletedCopyAssignment const&) = default;
DeletedCopyAssignment& operator=(DeletedCopyAssignment const&) = delete;
};
struct DeletedNonconstCopyAssignment {
DeletedNonconstCopyAssignment(DeletedNonconstCopyAssignment const&) = default;
DeletedNonconstCopyAssignment& operator=(DeletedNonconstCopyAssignment const&) = default;
DeletedNonconstCopyAssignment& operator=(DeletedNonconstCopyAssignment&) = delete;
};
struct DeletedMoveAssignment {
DeletedMoveAssignment(DeletedMoveAssignment&&) = default;
DeletedMoveAssignment& operator=(DeletedMoveAssignment&&) = delete;
};
struct DeletedConstMoveAssignment {
DeletedConstMoveAssignment(DeletedConstMoveAssignment&&) = default;
DeletedConstMoveAssignment& operator=(DeletedConstMoveAssignment&&) = delete;
};
static_assert(!std::indirectly_copyable_storable<DeletedCopyCtor*, DeletedCopyCtor*>);
static_assert(!std::indirectly_copyable_storable<DeletedNonconstCopyCtor*, DeletedNonconstCopyCtor*>);
static_assert(!std::indirectly_copyable_storable<DeletedMoveCtor*, DeletedMoveCtor*>);
static_assert(!std::indirectly_copyable_storable<DeletedConstMoveCtor*, DeletedConstMoveCtor*>);
static_assert(!std::indirectly_copyable_storable<DeletedCopyAssignment*, DeletedCopyAssignment*>);
static_assert(!std::indirectly_copyable_storable<DeletedNonconstCopyAssignment*, DeletedNonconstCopyAssignment*>);
static_assert(!std::indirectly_copyable_storable<DeletedMoveAssignment*, DeletedMoveAssignment*>);
static_assert(!std::indirectly_copyable_storable<DeletedConstMoveAssignment*, DeletedConstMoveAssignment*>);
struct InconsistentIterator {
struct ValueType;
struct ReferenceType {
ReferenceType& operator=(ValueType const&);
};
struct ValueType {
ValueType() = default;
ValueType(const ReferenceType&);
};
using value_type = ValueType;
ReferenceType& operator*() const;
};
// `ValueType` can be constructed with a `ReferenceType` and assigned to a `ReferenceType`, so it does model
// `indirectly_copyable_storable`.
static_assert( std::indirectly_copyable_storable<InconsistentIterator, InconsistentIterator>);
struct CommonType { };
// ReferenceType is a (proxy) reference for ValueType, but ValueType is not constructible from ReferenceType.
struct NotConstructibleFromRefIn {
struct ReferenceType;
struct ValueType {
ValueType(ReferenceType) = delete;
operator CommonType&() const;
};
struct ReferenceType {
operator CommonType&() const;
};
using value_type = ValueType;
ReferenceType& operator*() const;
};
template <template <class> class X, template <class> class Y>
struct std::basic_common_reference<NotConstructibleFromRefIn::ValueType,
NotConstructibleFromRefIn::ReferenceType, X, Y> {
using type = CommonType&;
};
template <template <class> class X, template <class> class Y>
struct std::basic_common_reference<NotConstructibleFromRefIn::ReferenceType,
NotConstructibleFromRefIn::ValueType, X, Y> {
using type = CommonType&;
};
static_assert(std::common_reference_with<NotConstructibleFromRefIn::ValueType&,
NotConstructibleFromRefIn::ReferenceType&>);
struct AssignableFromAnything {
template<class T>
AssignableFromAnything& operator=(T&&);
};
// A type that can't be constructed from its own reference isn't `indirectly_copyable_storable`, even when assigning it
// to a type that can be assigned from anything.
static_assert(!std::indirectly_copyable_storable<NotConstructibleFromRefIn, AssignableFromAnything*>);
// ReferenceType is a (proxy) reference for ValueType, but ValueType is not assignable from ReferenceType.
struct NotAssignableFromRefIn {
struct ReferenceType;
struct ValueType {
ValueType(ReferenceType);
ValueType& operator=(ReferenceType) = delete;
operator CommonType&() const;
};
struct ReferenceType {
operator CommonType&() const;
};
using value_type = ValueType;
ReferenceType& operator*() const;
};
template <template <class> class X, template <class> class Y>
struct std::basic_common_reference<NotAssignableFromRefIn::ValueType,
NotAssignableFromRefIn::ReferenceType, X, Y> {
using type = CommonType&;
};
template <template <class> class X, template <class> class Y>
struct std::basic_common_reference<NotAssignableFromRefIn::ReferenceType,
NotAssignableFromRefIn::ValueType, X, Y> {
using type = CommonType&;
};
static_assert(std::common_reference_with<NotAssignableFromRefIn::ValueType&, NotAssignableFromRefIn::ReferenceType&>);
// A type that can't be assigned from its own reference isn't `indirectly_copyable_storable`, even when assigning it
// to a type that can be assigned from anything.
static_assert(!std::indirectly_copyable_storable<NotAssignableFromRefIn, AssignableFromAnything*>);

View File

@ -0,0 +1,29 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-no-concepts
// template<class In, class Out>
// concept indirectly_copyable_storable;
#include <iterator>
template<class I, class O>
requires std::indirectly_copyable<I, O>
constexpr bool indirectly_copyable_storable_subsumption() {
return false;
}
template<class I, class O>
requires std::indirectly_copyable_storable<I, O>
constexpr bool indirectly_copyable_storable_subsumption() {
return true;
}
static_assert(indirectly_copyable_storable_subsumption<int*, int*>());

View File

@ -14,21 +14,38 @@
#include <iterator>
#include "MoveOnly.h"
#include "test_macros.h"
struct IndirectlyMovableWithInt {
int& operator*() const;
};
// Can move between pointers.
static_assert( std::indirectly_movable<int*, int*>);
static_assert( std::indirectly_movable<const int*, int*>);
static_assert(!std::indirectly_movable<int*, const int*>);
static_assert( std::indirectly_movable<const int*, int*>);
struct Empty {};
// Can move from a pointer into an array but arrays aren't considered indirectly movable-from.
static_assert( std::indirectly_movable<int*, int[2]>);
static_assert(!std::indirectly_movable<int[2], int*>);
static_assert(!std::indirectly_movable<int[2], int[2]>);
static_assert(!std::indirectly_movable<int(&)[2], int(&)[2]>);
struct MoveOnly {
MoveOnly(MoveOnly&&) = default;
MoveOnly(MoveOnly const&) = delete;
MoveOnly& operator=(MoveOnly&&) = default;
MoveOnly& operator=(MoveOnly const&) = delete;
MoveOnly() = default;
};
// Can't move between non-pointer types.
static_assert(!std::indirectly_movable<int*, int>);
static_assert(!std::indirectly_movable<int, int*>);
static_assert(!std::indirectly_movable<int, int>);
// Check some less common types.
static_assert(!std::indirectly_movable<void*, void*>);
static_assert(!std::indirectly_movable<int*, void*>);
static_assert(!std::indirectly_movable<int(), int()>);
static_assert(!std::indirectly_movable<int*, int()>);
static_assert(!std::indirectly_movable<void, void>);
// Can move move-only objects.
static_assert( std::indirectly_movable<MoveOnly*, MoveOnly*>);
static_assert(!std::indirectly_movable<MoveOnly*, const MoveOnly*>);
static_assert(!std::indirectly_movable<const MoveOnly*, const MoveOnly*>);
static_assert(!std::indirectly_movable<const MoveOnly*, MoveOnly*>);
template<class T>
struct PointerTo {
@ -36,23 +53,11 @@ struct PointerTo {
T& operator*() const;
};
static_assert( std::indirectly_movable<int*, int*>);
static_assert( std::indirectly_movable<const int*, int *>);
static_assert(!std::indirectly_movable<int*, const int *>);
static_assert(!std::indirectly_movable<const int*, const int *>);
static_assert( std::indirectly_movable<int*, int[2]>);
static_assert(!std::indirectly_movable<int[2], int*>);
static_assert(!std::indirectly_movable<int[2], int[2]>);
static_assert(!std::indirectly_movable<int(&)[2], int(&)[2]>);
static_assert(!std::indirectly_movable<int, int*>);
static_assert(!std::indirectly_movable<int, int>);
static_assert( std::indirectly_movable<Empty*, Empty*>);
static_assert( std::indirectly_movable<int*, IndirectlyMovableWithInt>);
static_assert(!std::indirectly_movable<Empty*, IndirectlyMovableWithInt>);
static_assert( std::indirectly_movable<int*, IndirectlyMovableWithInt>);
static_assert( std::indirectly_movable<MoveOnly*, MoveOnly*>);
static_assert(!std::indirectly_movable<MoveOnly*, const MoveOnly*>);
static_assert(!std::indirectly_movable<const MoveOnly*, const MoveOnly*>);
static_assert(!std::indirectly_movable<const MoveOnly*, MoveOnly*>);
static_assert( std::indirectly_movable<PointerTo<MoveOnly>, PointerTo<MoveOnly>>);
// Can copy through a dereferenceable class.
static_assert( std::indirectly_movable<int*, PointerTo<int>>);
static_assert(!std::indirectly_movable<int*, PointerTo<const int>>);
static_assert( std::indirectly_copyable<PointerTo<int>, PointerTo<int>>);
static_assert(!std::indirectly_copyable<PointerTo<int>, PointerTo<const int>>);
static_assert( std::indirectly_movable<MoveOnly*, PointerTo<MoveOnly>>);
static_assert( std::indirectly_movable<PointerTo<MoveOnly>, MoveOnly*>);
static_assert( std::indirectly_movable<PointerTo<MoveOnly>, PointerTo<MoveOnly>>);

View File

@ -14,8 +14,6 @@
#include <iterator>
#include <concepts>
template<std::indirectly_readable I, class O>
constexpr bool indirectly_movable_subsumption() {
return false;

View File

@ -14,56 +14,94 @@
#include <iterator>
#include "MoveOnly.h"
#include "test_macros.h"
struct Empty {};
struct MoveOnlyConvertible;
struct AssignableToMoveOnly;
struct MoveOnly {
MoveOnly(MoveOnly&&) = default;
MoveOnly(MoveOnly const&) = delete;
MoveOnly& operator=(MoveOnly&&) = default;
MoveOnly& operator=(MoveOnly const&) = delete;
MoveOnly() = default;
MoveOnly& operator=(MoveOnlyConvertible const&) = delete;
MoveOnly& operator=(AssignableToMoveOnly const&);
};
template<class T, class ValueType = T>
template <class T>
struct PointerTo {
using value_type = ValueType;
using value_type = T;
T& operator*() const;
};
// MoveOnlyConvertible is convertible to MoveOnly, but not assignable to it. This is
// implemented by explicitly deleting "operator=(MoveOnlyConvertible)" in MoveOnly.
struct MoveOnlyConvertible {
operator MoveOnly&() const;
// Copying the underlying object between pointers (or dereferenceable classes) works. This is a non-exhaustive check
// because this functionality comes from `indirectly_movable`.
static_assert( std::indirectly_movable_storable<int*, int*>);
static_assert( std::indirectly_movable_storable<const int*, int*>);
static_assert(!std::indirectly_movable_storable<int*, const int*>);
static_assert(!std::indirectly_movable_storable<const int*, const int*>);
static_assert( std::indirectly_movable_storable<int*, int[2]>);
static_assert(!std::indirectly_movable_storable<int[2], int*>);
static_assert( std::indirectly_movable_storable<MoveOnly*, MoveOnly*>);
static_assert( std::indirectly_movable_storable<PointerTo<MoveOnly>, PointerTo<MoveOnly>>);
// The dereference operator returns a different type from `value_type` and the reference type cannot be assigned from a
// `ValueType`.
struct NoAssignment {
struct ValueType;
struct ReferenceType {
ReferenceType& operator=(ValueType) = delete;
};
// `ValueType` is convertible to `ReferenceType` but not assignable to it. This is implemented by explicitly deleting
// `operator=(ValueType)` in `ReferenceType`.
struct ValueType {
operator ReferenceType&() const;
};
using value_type = ValueType;
ReferenceType& operator*() const;
};
// This type can be constructed with a MoveOnly and assigned to a MoveOnly, so it does
// model indirectly_movable_storable.
struct AssignableToMoveOnly {
AssignableToMoveOnly() = default;
AssignableToMoveOnly(const MoveOnly&);
};
// The case when `indirectly_writable<iter_rvalue_reference>` but not `indirectly_writable<iter_value>` (you can
// do `ReferenceType r = ValueType();` but not `r = ValueType();`).
static_assert( std::indirectly_writable<NoAssignment, std::iter_rvalue_reference_t<NoAssignment>>);
static_assert(!std::indirectly_writable<NoAssignment, std::iter_value_t<NoAssignment>>);
static_assert(!std::indirectly_movable_storable<NoAssignment, NoAssignment>);
struct DeletedMoveCtor {
DeletedMoveCtor(DeletedMoveCtor&&) = delete;
DeletedMoveCtor& operator=(DeletedMoveCtor&&) = default;
};
struct CommonType { };
struct DeletedMoveAssignment {
DeletedMoveAssignment(DeletedMoveAssignment&&) = default;
DeletedMoveAssignment& operator=(DeletedMoveAssignment&&) = delete;
};
static_assert(!std::indirectly_movable_storable<DeletedMoveCtor*, DeletedMoveCtor*>);
static_assert(!std::indirectly_movable_storable<DeletedMoveAssignment*, DeletedMoveAssignment*>);
struct InconsistentIterator {
struct ValueType;
struct ReferenceType {
ReferenceType& operator=(ValueType const&);
};
struct NotConstructibleFromRefIn {
struct ValueType {
ValueType() = default;
ValueType(const ReferenceType&);
};
using value_type = ValueType;
ReferenceType& operator*() const;
};
// `ValueType` can be constructed with a `ReferenceType` and assigned to a `ReferenceType`, so it does model
// `indirectly_movable_storable`.
static_assert( std::indirectly_movable_storable<InconsistentIterator, InconsistentIterator>);
// ReferenceType is a (proxy) reference for ValueType, but ValueType is not constructible from ReferenceType.
struct NotConstructibleFromRefIn {
struct CommonType { };
struct ReferenceType {
operator CommonType&() const;
};
struct ReferenceType {
struct ValueType {
ValueType(ReferenceType) = delete;
operator CommonType&() const;
};
@ -74,17 +112,35 @@ struct NotConstructibleFromRefIn {
template <template <class> class X, template <class> class Y>
struct std::basic_common_reference<NotConstructibleFromRefIn::ValueType,
NotConstructibleFromRefIn::ReferenceType, X, Y> {
using type = CommonType&;
using type = NotConstructibleFromRefIn::CommonType&;
};
template <template <class> class X, template <class> class Y>
struct std::basic_common_reference<NotConstructibleFromRefIn::ReferenceType,
NotConstructibleFromRefIn::ValueType, X, Y> {
using type = CommonType&;
using type = NotConstructibleFromRefIn::CommonType&;
};
static_assert(std::common_reference_with<NotConstructibleFromRefIn::ValueType&,
NotConstructibleFromRefIn::ReferenceType&>);
struct AssignableFromAnything {
template<class T>
AssignableFromAnything& operator=(T&&);
};
// A type that can't be constructed from its own reference isn't `indirectly_movable_storable`, even when assigning it
// to a type that can be assigned from anything.
static_assert( std::indirectly_movable_storable<int*, AssignableFromAnything*>);
static_assert(!std::indirectly_movable_storable<NotConstructibleFromRefIn, AssignableFromAnything*>);
// ReferenceType is a (proxy) reference for ValueType, but ValueType is not assignable from ReferenceType.
struct NotAssignableFromRefIn {
struct ReferenceType;
struct CommonType { };
struct ReferenceType {
operator CommonType&() const;
};
struct ValueType {
ValueType(ReferenceType);
@ -92,10 +148,6 @@ struct NotAssignableFromRefIn {
operator CommonType&() const;
};
struct ReferenceType {
operator CommonType&() const;
};
using value_type = ValueType;
ReferenceType& operator*() const;
};
@ -103,40 +155,17 @@ struct NotAssignableFromRefIn {
template <template <class> class X, template <class> class Y>
struct std::basic_common_reference<NotAssignableFromRefIn::ValueType,
NotAssignableFromRefIn::ReferenceType, X, Y> {
using type = CommonType&;
using type = NotAssignableFromRefIn::CommonType&;
};
template <template <class> class X, template <class> class Y>
struct std::basic_common_reference<NotAssignableFromRefIn::ReferenceType,
NotAssignableFromRefIn::ValueType, X, Y> {
using type = CommonType&;
using type = NotAssignableFromRefIn::CommonType&;
};
struct AnyWritable {
template<class T>
AnyWritable& operator=(T&&);
};
static_assert(std::common_reference_with<NotAssignableFromRefIn::ValueType&, NotAssignableFromRefIn::ReferenceType&>);
struct AnyOutput {
using value_type = AnyWritable;
AnyWritable& operator*() const;
};
static_assert( std::indirectly_movable_storable<int*, int*>);
static_assert( std::indirectly_movable_storable<const int*, int *>);
static_assert( std::indirectly_movable_storable<int*, int[2]>);
static_assert( std::indirectly_movable_storable<Empty*, Empty*>);
static_assert( std::indirectly_movable_storable<MoveOnly*, MoveOnly*>);
static_assert( std::indirectly_movable_storable<PointerTo<MoveOnly>, PointerTo<MoveOnly>>);
// The case when indirectly_writable<iter_rvalue_reference> but not indirectly_writable<iter_value>.
static_assert( std::indirectly_writable<
PointerTo<MoveOnly, MoveOnlyConvertible>,
std::iter_rvalue_reference_t<
PointerTo<MoveOnly, MoveOnlyConvertible>>>);
static_assert(!std::indirectly_movable_storable<PointerTo<MoveOnly, MoveOnlyConvertible>,
PointerTo<MoveOnly, MoveOnlyConvertible>>);
static_assert(!std::indirectly_movable_storable<DeletedMoveCtor*, DeletedMoveCtor*>);
static_assert( std::indirectly_movable_storable<PointerTo<MoveOnly, AssignableToMoveOnly>,
PointerTo<MoveOnly, AssignableToMoveOnly>>);
static_assert(!std::indirectly_movable_storable<NotConstructibleFromRefIn, AnyOutput>);
static_assert(!std::indirectly_movable_storable<NotAssignableFromRefIn, AnyOutput>);
// A type that can't be assigned from its own reference isn't `indirectly_movable_storable`, even when assigning it
// to a type that can be assigned from anything.
static_assert(!std::indirectly_movable_storable<NotAssignableFromRefIn, AssignableFromAnything*>);

View File

@ -14,8 +14,6 @@
#include <iterator>
#include <concepts>
template<class I, class O>
requires std::indirectly_movable<I, O>
constexpr bool indirectly_movable_storable_subsumption() {

View File

@ -25,4 +25,6 @@ static_assert(!std::sized_sentinel_for<iterator, iterator>);
static_assert(!std::input_iterator<iterator>);
static_assert(std::indirectly_movable<int*, iterator>);
static_assert(std::indirectly_movable_storable<int*, iterator>);
static_assert(std::indirectly_copyable<int*, iterator>);
static_assert(std::indirectly_copyable_storable<int*, iterator>);
static_assert(!std::indirectly_swappable<iterator, iterator>);

View File

@ -25,4 +25,6 @@ static_assert(!std::sized_sentinel_for<iterator, iterator>);
static_assert(!std::input_iterator<iterator>);
static_assert(std::indirectly_movable<int*, iterator>);
static_assert(std::indirectly_movable_storable<int*, iterator>);
static_assert(std::indirectly_copyable<int*, iterator>);
static_assert(std::indirectly_copyable_storable<int*, iterator>);
static_assert(!std::indirectly_swappable<iterator, iterator>);

View File

@ -24,4 +24,6 @@ static_assert(!std::sentinel_for<iterator, iterator>);
static_assert(!std::input_iterator<iterator>);
static_assert(std::indirectly_movable<int*, iterator>);
static_assert(std::indirectly_movable_storable<int*, iterator>);
static_assert(std::indirectly_copyable<int*, iterator>);
static_assert(std::indirectly_copyable_storable<int*, iterator>);
static_assert(!std::indirectly_swappable<iterator, iterator>);

View File

@ -23,4 +23,6 @@ static_assert(std::sentinel_for<iterator, iterator>);
static_assert(std::sized_sentinel_for<iterator, iterator>);
static_assert(!std::indirectly_movable<int*, iterator>);
static_assert(!std::indirectly_movable_storable<int*, iterator>);
static_assert(!std::indirectly_copyable<int*, iterator>);
static_assert(!std::indirectly_copyable_storable<int*, iterator>);
static_assert(!std::indirectly_swappable<iterator, iterator>);

View File

@ -31,6 +31,8 @@ static_assert(!std::random_access_iterator<reverse_bidirectional_iterator>);
static_assert(!std::sized_sentinel_for<reverse_bidirectional_iterator, reverse_bidirectional_iterator>);
static_assert( std::indirectly_movable<reverse_bidirectional_iterator, reverse_bidirectional_iterator>);
static_assert( std::indirectly_movable_storable<reverse_bidirectional_iterator, reverse_bidirectional_iterator>);
static_assert( std::indirectly_copyable<reverse_bidirectional_iterator, reverse_bidirectional_iterator>);
static_assert( std::indirectly_copyable_storable<reverse_bidirectional_iterator, reverse_bidirectional_iterator>);
static_assert( std::indirectly_swappable<reverse_bidirectional_iterator, reverse_bidirectional_iterator>);
using reverse_random_access_iterator = std::reverse_iterator<random_access_iterator<int*>>;
@ -40,6 +42,8 @@ static_assert(!std::contiguous_iterator<reverse_random_access_iterator>);
static_assert(std::sized_sentinel_for<reverse_random_access_iterator, reverse_random_access_iterator>);
static_assert( std::indirectly_movable<reverse_random_access_iterator, reverse_random_access_iterator>);
static_assert( std::indirectly_movable_storable<reverse_random_access_iterator, reverse_random_access_iterator>);
static_assert( std::indirectly_copyable<reverse_random_access_iterator, reverse_random_access_iterator>);
static_assert( std::indirectly_copyable_storable<reverse_random_access_iterator, reverse_random_access_iterator>);
static_assert( std::indirectly_swappable<reverse_random_access_iterator, reverse_random_access_iterator>);
using reverse_contiguous_iterator = std::reverse_iterator<contiguous_iterator<int*>>;
@ -49,4 +53,6 @@ static_assert(!std::contiguous_iterator<reverse_contiguous_iterator>);
static_assert(std::sized_sentinel_for<reverse_contiguous_iterator, reverse_contiguous_iterator>);
static_assert( std::indirectly_movable<reverse_contiguous_iterator, reverse_contiguous_iterator>);
static_assert( std::indirectly_movable_storable<reverse_contiguous_iterator, reverse_contiguous_iterator>);
static_assert( std::indirectly_copyable<reverse_contiguous_iterator, reverse_contiguous_iterator>);
static_assert( std::indirectly_copyable_storable<reverse_contiguous_iterator, reverse_contiguous_iterator>);
static_assert( std::indirectly_swappable<reverse_contiguous_iterator, reverse_contiguous_iterator>);

View File

@ -25,4 +25,6 @@ static_assert(!std::sized_sentinel_for<iterator, iterator>);
static_assert(std::input_iterator<iterator>);
static_assert(!std::indirectly_movable<int*, iterator>);
static_assert(!std::indirectly_movable_storable<int*, iterator>);
static_assert(!std::indirectly_copyable<int*, iterator>);
static_assert(!std::indirectly_copyable_storable<int*, iterator>);
static_assert(!std::indirectly_swappable<iterator, iterator>);

View File

@ -26,4 +26,6 @@ static_assert(std::sentinel_for<iterator, iterator>);
static_assert(!std::sized_sentinel_for<iterator, iterator>);
static_assert(std::indirectly_movable<iterator, char*>);
static_assert(std::indirectly_movable_storable<iterator, char*>);
static_assert(std::indirectly_copyable<iterator, char*>);
static_assert(std::indirectly_copyable_storable<iterator, char*>);
static_assert(!std::indirectly_swappable<iterator, iterator>);

View File

@ -25,4 +25,6 @@ static_assert(!std::sized_sentinel_for<iterator, iterator>);
static_assert(!std::input_iterator<iterator>);
static_assert(std::indirectly_movable<int*, iterator>);
static_assert(std::indirectly_movable_storable<int*, iterator>);
static_assert(std::indirectly_copyable<int*, iterator>);
static_assert(std::indirectly_copyable_storable<int*, iterator>);
static_assert(!std::indirectly_swappable<iterator, iterator>);

View File

@ -26,4 +26,6 @@ static_assert(!std::sized_sentinel_for<iterator, iterator>);
static_assert(!std::input_iterator<iterator>);
static_assert(std::indirectly_movable<char*, iterator>);
static_assert(std::indirectly_movable_storable<char*, iterator>);
static_assert(std::indirectly_copyable<char*, iterator>);
static_assert(std::indirectly_copyable_storable<char*, iterator>);
static_assert(!std::indirectly_swappable<iterator, iterator>);

View File

@ -22,4 +22,6 @@ static_assert(std::sentinel_for<std::cregex_iterator, std::cregex_iterator>);
static_assert(!std::sized_sentinel_for<std::cregex_iterator, std::cregex_iterator>);
static_assert(!std::indirectly_movable<std::cregex_iterator, std::cregex_iterator>);
static_assert(!std::indirectly_movable_storable<std::cregex_iterator, std::cregex_iterator>);
static_assert(!std::indirectly_copyable<std::cregex_iterator, std::cregex_iterator>);
static_assert(!std::indirectly_copyable_storable<std::cregex_iterator, std::cregex_iterator>);
static_assert(!std::indirectly_swappable<std::cregex_iterator, std::cregex_iterator>);

View File

@ -22,4 +22,6 @@ static_assert(std::sentinel_for<std::cregex_token_iterator, std::cregex_token_it
static_assert(!std::sized_sentinel_for<std::cregex_token_iterator, std::cregex_token_iterator>);
static_assert(!std::indirectly_movable<std::cregex_token_iterator, std::cregex_token_iterator>);
static_assert(!std::indirectly_movable_storable<std::cregex_token_iterator, std::cregex_token_iterator>);
static_assert(!std::indirectly_copyable<std::cregex_token_iterator, std::cregex_token_iterator>);
static_assert(!std::indirectly_copyable_storable<std::cregex_token_iterator, std::cregex_token_iterator>);
static_assert(!std::indirectly_swappable<std::cregex_token_iterator, std::cregex_token_iterator>);

View File

@ -39,6 +39,14 @@ static_assert( std::indirectly_movable<iterator, reverse_iterator>);
static_assert( std::indirectly_movable_storable<iterator, reverse_iterator>);
static_assert(!std::indirectly_movable<iterator, const_reverse_iterator>);
static_assert(!std::indirectly_movable_storable<iterator, const_reverse_iterator>);
static_assert( std::indirectly_copyable<iterator, iterator>);
static_assert( std::indirectly_copyable_storable<iterator, iterator>);
static_assert(!std::indirectly_copyable<iterator, const_iterator>);
static_assert(!std::indirectly_copyable_storable<iterator, const_iterator>);
static_assert( std::indirectly_copyable<iterator, reverse_iterator>);
static_assert( std::indirectly_copyable_storable<iterator, reverse_iterator>);
static_assert(!std::indirectly_copyable<iterator, const_reverse_iterator>);
static_assert(!std::indirectly_copyable_storable<iterator, const_reverse_iterator>);
static_assert( std::indirectly_swappable<iterator, iterator>);
static_assert(std::contiguous_iterator<const_iterator>);
@ -59,4 +67,12 @@ static_assert( std::indirectly_movable<const_iterator, reverse_iterator>);
static_assert( std::indirectly_movable_storable<const_iterator, reverse_iterator>);
static_assert(!std::indirectly_movable<const_iterator, const_reverse_iterator>);
static_assert(!std::indirectly_movable_storable<const_iterator, const_reverse_iterator>);
static_assert( std::indirectly_copyable<const_iterator, iterator>);
static_assert( std::indirectly_copyable_storable<const_iterator, iterator>);
static_assert(!std::indirectly_copyable<const_iterator, const_iterator>);
static_assert(!std::indirectly_copyable_storable<const_iterator, const_iterator>);
static_assert( std::indirectly_copyable<const_iterator, reverse_iterator>);
static_assert( std::indirectly_copyable_storable<const_iterator, reverse_iterator>);
static_assert(!std::indirectly_copyable<const_iterator, const_reverse_iterator>);
static_assert(!std::indirectly_copyable_storable<const_iterator, const_reverse_iterator>);
static_assert(!std::indirectly_swappable<const_iterator, const_iterator>);

View File

@ -35,6 +35,8 @@ static_assert(!std::sized_sentinel_for<iterator, reverse_iterator>);
static_assert(!std::sized_sentinel_for<iterator, const_reverse_iterator>);
static_assert(std::indirectly_movable<iterator, char*>);
static_assert(std::indirectly_movable_storable<iterator, char*>);
static_assert(std::indirectly_copyable<iterator, char*>);
static_assert(std::indirectly_copyable_storable<iterator, char*>);
static_assert(!std::indirectly_swappable<iterator, iterator>);
static_assert(std::contiguous_iterator<const_iterator>);

View File

@ -20,6 +20,8 @@ static_assert(std::indirectly_writable<std::unique_ptr<int>, int>);
static_assert(!std::weakly_incrementable<std::unique_ptr<int> >);
static_assert(std::indirectly_movable<std::unique_ptr<int>, std::unique_ptr<int>>);
static_assert(std::indirectly_movable_storable<std::unique_ptr<int>, std::unique_ptr<int>>);
static_assert(std::indirectly_copyable<std::unique_ptr<int>, std::unique_ptr<int>>);
static_assert(std::indirectly_copyable_storable<std::unique_ptr<int>, std::unique_ptr<int>>);
static_assert(std::indirectly_swappable<std::unique_ptr<int>, std::unique_ptr<int> >);
static_assert(!std::indirectly_readable<std::unique_ptr<void> >);
@ -27,3 +29,5 @@ static_assert(!std::indirectly_writable<std::unique_ptr<void>, void>);
static_assert(!std::weakly_incrementable<std::unique_ptr<void> >);
static_assert(!std::indirectly_movable<std::unique_ptr<void>, std::unique_ptr<void>>);
static_assert(!std::indirectly_movable_storable<std::unique_ptr<void>, std::unique_ptr<void>>);
static_assert(!std::indirectly_copyable<std::unique_ptr<void>, std::unique_ptr<void>>);
static_assert(!std::indirectly_copyable_storable<std::unique_ptr<void>, std::unique_ptr<void>>);

View File

@ -20,6 +20,8 @@ static_assert(std::indirectly_writable<std::shared_ptr<int>, int>);
static_assert(!std::weakly_incrementable<std::shared_ptr<int> >);
static_assert(std::indirectly_movable<std::shared_ptr<int>, std::shared_ptr<int>>);
static_assert(std::indirectly_movable_storable<std::shared_ptr<int>, std::shared_ptr<int>>);
static_assert(std::indirectly_copyable<std::shared_ptr<int>, std::shared_ptr<int>>);
static_assert(std::indirectly_copyable_storable<std::shared_ptr<int>, std::shared_ptr<int>>);
static_assert(std::indirectly_swappable<std::shared_ptr<int>, std::shared_ptr<int> >);
static_assert(!std::indirectly_readable<std::shared_ptr<void> >);
@ -27,3 +29,5 @@ static_assert(!std::indirectly_writable<std::shared_ptr<void>, void>);
static_assert(!std::weakly_incrementable<std::shared_ptr<void> >);
static_assert(!std::indirectly_movable<std::shared_ptr<void>, std::shared_ptr<void>>);
static_assert(!std::indirectly_movable_storable<std::shared_ptr<void>, std::shared_ptr<void>>);
static_assert(!std::indirectly_copyable<std::shared_ptr<void>, std::shared_ptr<void>>);
static_assert(!std::indirectly_copyable_storable<std::shared_ptr<void>, std::shared_ptr<void>>);

View File

@ -20,3 +20,5 @@ static_assert(!std::indirectly_writable<std::optional<int>, int>);
static_assert(!std::weakly_incrementable<std::optional<int> >);
static_assert(!std::indirectly_movable<std::optional<int>, std::optional<int>>);
static_assert(!std::indirectly_movable_storable<std::optional<int>, std::optional<int>>);
static_assert(!std::indirectly_copyable<std::optional<int>, std::optional<int>>);
static_assert(!std::indirectly_copyable_storable<std::optional<int>, std::optional<int>>);