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