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 11 // template<class In, class Out> 12 // concept indirectly_copyable; 13 14 #include <iterator> 15 16 #include "MoveOnly.h" 17 #include "test_macros.h" 18 19 struct CopyOnly { 20 CopyOnly() = default; 21 22 CopyOnly(CopyOnly const&) = default; 23 CopyOnly& operator=(CopyOnly const&) = default; 24 25 CopyOnly(CopyOnly&&) = delete; 26 CopyOnly& operator=(CopyOnly&&) = delete; 27 }; 28 29 // Can copy the underlying objects between pointers. 30 static_assert( std::indirectly_copyable<int*, int*>); 31 static_assert( std::indirectly_copyable<const int*, int *>); 32 33 // Can't copy if the output pointer is const. 34 static_assert(!std::indirectly_copyable<int*, const int *>); 35 static_assert(!std::indirectly_copyable<const int*, const int *>); 36 37 // Can copy from a pointer into an array but arrays aren't considered indirectly copyable-from. 38 static_assert( std::indirectly_copyable<int*, int[2]>); 39 static_assert(!std::indirectly_copyable<int[2], int*>); 40 static_assert(!std::indirectly_copyable<int[2], int[2]>); 41 static_assert(!std::indirectly_copyable<int(&)[2], int(&)[2]>); 42 43 // Can't copy between non-pointer types. 44 static_assert(!std::indirectly_copyable<int*, int>); 45 static_assert(!std::indirectly_copyable<int, int*>); 46 static_assert(!std::indirectly_copyable<int, int>); 47 48 // Check some less common types. 49 static_assert(!std::indirectly_movable<void*, void*>); 50 static_assert(!std::indirectly_movable<int*, void*>); 51 static_assert(!std::indirectly_movable<int(), int()>); 52 static_assert(!std::indirectly_movable<int*, int()>); 53 static_assert(!std::indirectly_movable<void, void>); 54 55 // Can't copy move-only objects. 56 static_assert(!std::indirectly_copyable<MoveOnly*, MoveOnly*>); 57 static_assert(!std::indirectly_copyable<MoveOnly*, const MoveOnly*>); 58 static_assert(!std::indirectly_copyable<const MoveOnly*, MoveOnly*>); 59 static_assert(!std::indirectly_copyable<const MoveOnly*, const MoveOnly*>); 60 61 // Can copy copy-only objects. 62 static_assert( std::indirectly_copyable<CopyOnly*, CopyOnly*>); 63 static_assert(!std::indirectly_copyable<CopyOnly*, const CopyOnly*>); 64 static_assert( std::indirectly_copyable<const CopyOnly*, CopyOnly*>); 65 static_assert(!std::indirectly_copyable<const CopyOnly*, const CopyOnly*>); 66 67 template<class T> 68 struct PointerTo { 69 using value_type = T; 70 T& operator*() const; 71 }; 72 73 // Can copy through a dereferenceable class. 74 static_assert( std::indirectly_copyable<int*, PointerTo<int>>); 75 static_assert(!std::indirectly_copyable<int*, PointerTo<const int>>); 76 static_assert( std::indirectly_copyable<PointerTo<int>, PointerTo<int>>); 77 static_assert(!std::indirectly_copyable<PointerTo<int>, PointerTo<const int>>); 78 static_assert( std::indirectly_copyable<CopyOnly*, PointerTo<CopyOnly>>); 79 static_assert( std::indirectly_copyable<PointerTo<CopyOnly>, CopyOnly*>); 80 static_assert( std::indirectly_copyable<PointerTo<CopyOnly>, PointerTo<CopyOnly>>); 81