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, c++20 10 11 // constexpr expected(const expected& rhs); 12 // 13 // Effects: If rhs.has_value() is true, direct-non-list-initializes val with *rhs. 14 // Otherwise, direct-non-list-initializes unex with rhs.error(). 15 // 16 // Postconditions: rhs.has_value() == this->has_value(). 17 // 18 // Throws: Any exception thrown by the initialization of val or unex. 19 // 20 // Remarks: This constructor is defined as deleted unless 21 // - is_copy_constructible_v<T> is true and 22 // - is_copy_constructible_v<E> is true. 23 // 24 // This constructor is trivial if 25 // - is_trivially_copy_constructible_v<T> is true and 26 // - is_trivially_copy_constructible_v<E> is true. 27 28 #include <cassert> 29 #include <expected> 30 #include <type_traits> 31 #include <utility> 32 33 #include "test_macros.h" 34 #include "../../types.h" 35 36 struct NonCopyable { 37 NonCopyable(const NonCopyable&) = delete; 38 }; 39 40 struct CopyableNonTrivial { 41 int i; 42 constexpr CopyableNonTrivial(int ii) : i(ii) {} 43 constexpr CopyableNonTrivial(const CopyableNonTrivial& o) { i = o.i; } 44 friend constexpr bool operator==(const CopyableNonTrivial&, const CopyableNonTrivial&) = default; 45 }; 46 47 // Test: This constructor is defined as deleted unless 48 // - is_copy_constructible_v<T> is true and 49 // - is_copy_constructible_v<E> is true. 50 static_assert(std::is_copy_constructible_v<std::expected<int, int>>); 51 static_assert(std::is_copy_constructible_v<std::expected<CopyableNonTrivial, int>>); 52 static_assert(std::is_copy_constructible_v<std::expected<int, CopyableNonTrivial>>); 53 static_assert(std::is_copy_constructible_v<std::expected<CopyableNonTrivial, CopyableNonTrivial>>); 54 static_assert(!std::is_copy_constructible_v<std::expected<NonCopyable, int>>); 55 static_assert(!std::is_copy_constructible_v<std::expected<int, NonCopyable>>); 56 static_assert(!std::is_copy_constructible_v<std::expected<NonCopyable, NonCopyable>>); 57 58 // Test: This constructor is trivial if 59 // - is_trivially_copy_constructible_v<T> is true and 60 // - is_trivially_copy_constructible_v<E> is true. 61 static_assert(std::is_trivially_copy_constructible_v<std::expected<int, int>>); 62 static_assert(!std::is_trivially_copy_constructible_v<std::expected<CopyableNonTrivial, int>>); 63 static_assert(!std::is_trivially_copy_constructible_v<std::expected<int, CopyableNonTrivial>>); 64 static_assert(!std::is_trivially_copy_constructible_v<std::expected<CopyableNonTrivial, CopyableNonTrivial>>); 65 66 struct Any { 67 constexpr Any() = default; 68 constexpr Any(const Any&) = default; 69 constexpr Any& operator=(const Any&) = default; 70 71 template <class T> 72 requires(!std::is_same_v<Any, std::decay_t<T>> && std::is_copy_constructible_v<std::decay_t<T>>) 73 constexpr Any(T&&) {} 74 }; 75 76 constexpr bool test() { 77 // copy the value non-trivial 78 { 79 const std::expected<CopyableNonTrivial, int> e1(5); 80 auto e2 = e1; 81 assert(e2.has_value()); 82 assert(e2.value().i == 5); 83 } 84 85 // copy the error non-trivial 86 { 87 const std::expected<int, CopyableNonTrivial> e1(std::unexpect, 5); 88 auto e2 = e1; 89 assert(!e2.has_value()); 90 assert(e2.error().i == 5); 91 } 92 93 // copy the value trivial 94 { 95 const std::expected<int, int> e1(5); 96 auto e2 = e1; 97 assert(e2.has_value()); 98 assert(e2.value() == 5); 99 } 100 101 // copy the error trivial 102 { 103 const std::expected<int, int> e1(std::unexpect, 5); 104 auto e2 = e1; 105 assert(!e2.has_value()); 106 assert(e2.error() == 5); 107 } 108 109 // copy TailClobberer as value 110 { 111 const std::expected<TailClobberer<0>, bool> e1; 112 auto e2 = e1; 113 assert(e2.has_value()); 114 } 115 116 // copy TailClobberer as error 117 { 118 const std::expected<bool, TailClobberer<1>> e1(std::unexpect); 119 auto e2 = e1; 120 assert(!e2.has_value()); 121 } 122 123 { 124 // TODO: Drop this once AppleClang is upgraded 125 #ifndef TEST_COMPILER_APPLE_CLANG 126 // https://github.com/llvm/llvm-project/issues/92676 127 std::expected<Any, int> e1; 128 auto e2 = e1; 129 assert(e2.has_value()); 130 #endif 131 } 132 133 return true; 134 } 135 136 void testException() { 137 #ifndef TEST_HAS_NO_EXCEPTIONS 138 struct Throwing { 139 Throwing() = default; 140 Throwing(const Throwing&) { throw Except{}; } 141 }; 142 143 // throw on copying value 144 { 145 const std::expected<Throwing, int> e1; 146 try { 147 [[maybe_unused]] auto e2 = e1; 148 assert(false); 149 } catch (Except) { 150 } 151 } 152 153 // throw on copying error 154 { 155 const std::expected<int, Throwing> e1(std::unexpect); 156 try { 157 [[maybe_unused]] auto e2 = e1; 158 assert(false); 159 } catch (Except) { 160 } 161 } 162 163 #endif // TEST_HAS_NO_EXCEPTIONS 164 } 165 166 int main(int, char**) { 167 test(); 168 static_assert(test()); 169 testException(); 170 return 0; 171 } 172