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