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