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 false, direct-non-list-initializes unex with rhs.error(). 14 // 15 // Postconditions: rhs.has_value() == this->has_value(). 16 // 17 // Throws: Any exception thrown by the initialization of unex. 18 // 19 // Remarks: 20 // - This constructor is defined as deleted unless is_copy_constructible_v<E> is true. 21 // - This constructor is trivial if is_trivially_copy_constructible_v<E> is true. 22 23 #include <cassert> 24 #include <expected> 25 #include <type_traits> 26 #include <utility> 27 28 #include "test_macros.h" 29 #include "../../types.h" 30 31 struct NonCopyable { 32 NonCopyable(const NonCopyable&) = delete; 33 }; 34 35 struct CopyableNonTrivial { 36 int i; 37 constexpr CopyableNonTrivial(int ii) : i(ii) {} 38 constexpr CopyableNonTrivial(const CopyableNonTrivial& o) { i = o.i; } 39 friend constexpr bool operator==(const CopyableNonTrivial&, const CopyableNonTrivial&) = default; 40 }; 41 42 // Test: This constructor is defined as deleted unless is_copy_constructible_v<E> is true. 43 static_assert(std::is_copy_constructible_v<std::expected<void, int>>); 44 static_assert(std::is_copy_constructible_v<std::expected<void, CopyableNonTrivial>>); 45 static_assert(!std::is_copy_constructible_v<std::expected<void, NonCopyable>>); 46 47 // Test: This constructor is trivial if is_trivially_copy_constructible_v<E> is true. 48 static_assert(std::is_trivially_copy_constructible_v<std::expected<void, int>>); 49 static_assert(!std::is_trivially_copy_constructible_v<std::expected<void, CopyableNonTrivial>>); 50 51 constexpr bool test() { 52 // copy the error non-trivial 53 { 54 const std::expected<void, CopyableNonTrivial> e1(std::unexpect, 5); 55 auto e2 = e1; 56 assert(!e2.has_value()); 57 assert(e2.error().i == 5); 58 } 59 60 // copy the error trivial 61 { 62 const std::expected<void, int> e1(std::unexpect, 5); 63 auto e2 = e1; 64 assert(!e2.has_value()); 65 assert(e2.error() == 5); 66 } 67 68 // copy TailClobberer as error 69 { 70 const std::expected<void, TailClobberer<1>> e1(std::unexpect); 71 auto e2 = e1; 72 assert(!e2.has_value()); 73 } 74 75 return true; 76 } 77 78 void testException() { 79 #ifndef TEST_HAS_NO_EXCEPTIONS 80 struct Throwing { 81 Throwing() = default; 82 Throwing(const Throwing&) { throw Except{}; } 83 }; 84 85 // throw on copying error 86 { 87 const std::expected<void, Throwing> e1(std::unexpect); 88 try { 89 [[maybe_unused]] auto e2 = e1; 90 assert(false); 91 } catch (Except) { 92 } 93 } 94 95 #endif // TEST_HAS_NO_EXCEPTIONS 96 } 97 98 int main(int, char**) { 99 test(); 100 static_assert(test()); 101 testException(); 102 return 0; 103 } 104