1*e65d3760SKonstantin Varlamov //===----------------------------------------------------------------------===//
2*e65d3760SKonstantin Varlamov //
3*e65d3760SKonstantin Varlamov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*e65d3760SKonstantin Varlamov // See https://llvm.org/LICENSE.txt for license information.
5*e65d3760SKonstantin Varlamov // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*e65d3760SKonstantin Varlamov //
7*e65d3760SKonstantin Varlamov //===----------------------------------------------------------------------===//
8*e65d3760SKonstantin Varlamov 
9*e65d3760SKonstantin Varlamov // UNSUPPORTED: c++03, c++11, c++14, c++17
10*e65d3760SKonstantin Varlamov 
11*e65d3760SKonstantin Varlamov // template<class In, class Out>
12*e65d3760SKonstantin Varlamov // concept indirectly_copyable;
13*e65d3760SKonstantin Varlamov 
14*e65d3760SKonstantin Varlamov #include <iterator>
15*e65d3760SKonstantin Varlamov 
16*e65d3760SKonstantin Varlamov #include "MoveOnly.h"
17*e65d3760SKonstantin Varlamov #include "test_macros.h"
18*e65d3760SKonstantin Varlamov 
19*e65d3760SKonstantin Varlamov struct CopyOnly {
20*e65d3760SKonstantin Varlamov   CopyOnly() = default;
21*e65d3760SKonstantin Varlamov 
22*e65d3760SKonstantin Varlamov   CopyOnly(CopyOnly const&) = default;
23*e65d3760SKonstantin Varlamov   CopyOnly& operator=(CopyOnly const&) = default;
24*e65d3760SKonstantin Varlamov 
25*e65d3760SKonstantin Varlamov   CopyOnly(CopyOnly&&) = delete;
26*e65d3760SKonstantin Varlamov   CopyOnly& operator=(CopyOnly&&) = delete;
27*e65d3760SKonstantin Varlamov };
28*e65d3760SKonstantin Varlamov 
29*e65d3760SKonstantin Varlamov // Can copy the underlying objects between pointers.
30*e65d3760SKonstantin Varlamov static_assert( std::indirectly_copyable<int*, int*>);
31*e65d3760SKonstantin Varlamov static_assert( std::indirectly_copyable<const int*, int *>);
32*e65d3760SKonstantin Varlamov 
33*e65d3760SKonstantin Varlamov // Can't copy if the output pointer is const.
34*e65d3760SKonstantin Varlamov static_assert(!std::indirectly_copyable<int*, const int *>);
35*e65d3760SKonstantin Varlamov static_assert(!std::indirectly_copyable<const int*, const int *>);
36*e65d3760SKonstantin Varlamov 
37*e65d3760SKonstantin Varlamov // Can copy from a pointer into an array but arrays aren't considered indirectly copyable-from.
38*e65d3760SKonstantin Varlamov static_assert( std::indirectly_copyable<int*, int[2]>);
39*e65d3760SKonstantin Varlamov static_assert(!std::indirectly_copyable<int[2], int*>);
40*e65d3760SKonstantin Varlamov static_assert(!std::indirectly_copyable<int[2], int[2]>);
41*e65d3760SKonstantin Varlamov static_assert(!std::indirectly_copyable<int(&)[2], int(&)[2]>);
42*e65d3760SKonstantin Varlamov 
43*e65d3760SKonstantin Varlamov // Can't copy between non-pointer types.
44*e65d3760SKonstantin Varlamov static_assert(!std::indirectly_copyable<int*, int>);
45*e65d3760SKonstantin Varlamov static_assert(!std::indirectly_copyable<int, int*>);
46*e65d3760SKonstantin Varlamov static_assert(!std::indirectly_copyable<int, int>);
47*e65d3760SKonstantin Varlamov 
48*e65d3760SKonstantin Varlamov // Check some less common types.
49*e65d3760SKonstantin Varlamov static_assert(!std::indirectly_movable<void*, void*>);
50*e65d3760SKonstantin Varlamov static_assert(!std::indirectly_movable<int*, void*>);
51*e65d3760SKonstantin Varlamov static_assert(!std::indirectly_movable<int(), int()>);
52*e65d3760SKonstantin Varlamov static_assert(!std::indirectly_movable<int*, int()>);
53*e65d3760SKonstantin Varlamov static_assert(!std::indirectly_movable<void, void>);
54*e65d3760SKonstantin Varlamov 
55*e65d3760SKonstantin Varlamov // Can't copy move-only objects.
56*e65d3760SKonstantin Varlamov static_assert(!std::indirectly_copyable<MoveOnly*, MoveOnly*>);
57*e65d3760SKonstantin Varlamov static_assert(!std::indirectly_copyable<MoveOnly*, const MoveOnly*>);
58*e65d3760SKonstantin Varlamov static_assert(!std::indirectly_copyable<const MoveOnly*, MoveOnly*>);
59*e65d3760SKonstantin Varlamov static_assert(!std::indirectly_copyable<const MoveOnly*, const MoveOnly*>);
60*e65d3760SKonstantin Varlamov 
61*e65d3760SKonstantin Varlamov // Can copy copy-only objects.
62*e65d3760SKonstantin Varlamov static_assert( std::indirectly_copyable<CopyOnly*, CopyOnly*>);
63*e65d3760SKonstantin Varlamov static_assert(!std::indirectly_copyable<CopyOnly*, const CopyOnly*>);
64*e65d3760SKonstantin Varlamov static_assert( std::indirectly_copyable<const CopyOnly*, CopyOnly*>);
65*e65d3760SKonstantin Varlamov static_assert(!std::indirectly_copyable<const CopyOnly*, const CopyOnly*>);
66*e65d3760SKonstantin Varlamov 
67*e65d3760SKonstantin Varlamov template<class T>
68*e65d3760SKonstantin Varlamov struct PointerTo {
69*e65d3760SKonstantin Varlamov   using value_type = T;
70*e65d3760SKonstantin Varlamov   T& operator*() const;
71*e65d3760SKonstantin Varlamov };
72*e65d3760SKonstantin Varlamov 
73*e65d3760SKonstantin Varlamov // Can copy through a dereferenceable class.
74*e65d3760SKonstantin Varlamov static_assert( std::indirectly_copyable<int*, PointerTo<int>>);
75*e65d3760SKonstantin Varlamov static_assert(!std::indirectly_copyable<int*, PointerTo<const int>>);
76*e65d3760SKonstantin Varlamov static_assert( std::indirectly_copyable<PointerTo<int>, PointerTo<int>>);
77*e65d3760SKonstantin Varlamov static_assert(!std::indirectly_copyable<PointerTo<int>, PointerTo<const int>>);
78*e65d3760SKonstantin Varlamov static_assert( std::indirectly_copyable<CopyOnly*, PointerTo<CopyOnly>>);
79*e65d3760SKonstantin Varlamov static_assert( std::indirectly_copyable<PointerTo<CopyOnly>, CopyOnly*>);
80*e65d3760SKonstantin Varlamov static_assert( std::indirectly_copyable<PointerTo<CopyOnly>, PointerTo<CopyOnly>>);
81