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 // template<class G> 12 // constexpr explicit(!is_convertible_v<G, E>) expected(unexpected<G>&& e); 13 // 14 // Let GF be G 15 // 16 // Constraints: is_constructible_v<E, GF> is true. 17 // 18 // Effects: Direct-non-list-initializes unex with std::forward<GF>(e.error()). 19 // 20 // Postconditions: has_value() is false. 21 // 22 // Throws: Any exception thrown by the initialization of unex. 23 24 #include <cassert> 25 #include <expected> 26 #include <type_traits> 27 #include <utility> 28 29 #include "MoveOnly.h" 30 #include "test_macros.h" 31 #include "../../types.h" 32 33 // Test Constraints 34 static_assert(std::is_constructible_v<std::expected<int, int>, std::unexpected<int>>); 35 static_assert(std::is_constructible_v<std::expected<int, MoveOnly>, std::unexpected<MoveOnly>>); 36 37 // !is_constructible_v<E, GF> 38 struct foo {}; 39 static_assert(!std::is_constructible_v<std::expected<int, int>, std::unexpected<foo>>); 40 41 // explicit(!is_convertible_v<G, E>) 42 struct NotConvertible { 43 explicit NotConvertible(int); 44 }; 45 static_assert(std::is_convertible_v<std::unexpected<int>&&, std::expected<int, int>>); 46 static_assert(!std::is_convertible_v<std::unexpected<int>&&, std::expected<int, NotConvertible>>); 47 48 struct MyInt { 49 int i; 50 constexpr MyInt(int ii) : i(ii) {} 51 friend constexpr bool operator==(const MyInt&, const MyInt&) = default; 52 }; 53 54 template <class Err, class V = int> 55 constexpr void testInt() { 56 std::unexpected<int> u(5); 57 std::expected<V, Err> e(std::move(u)); 58 assert(!e.has_value()); 59 assert(e.error() == 5); 60 } 61 62 constexpr void testMoveOnly() { 63 std::unexpected<MoveOnly> u(MoveOnly(5)); 64 std::expected<int, MoveOnly> e(std::move(u)); 65 assert(!e.has_value()); 66 assert(e.error() == 5); 67 assert(u.error() == 0); 68 } 69 70 constexpr bool test() { 71 testInt<int>(); 72 testInt<MyInt>(); 73 testInt<MoveOnly>(); 74 testInt<TailClobberer<1>, bool>(); 75 testMoveOnly(); 76 return true; 77 } 78 79 void testException() { 80 #ifndef TEST_HAS_NO_EXCEPTIONS 81 struct Throwing { 82 Throwing(int) { throw Except{}; } 83 }; 84 85 { 86 std::unexpected<int> u(5); 87 try { 88 [[maybe_unused]] std::expected<int, Throwing> e(std::move(u)); 89 assert(false); 90 } catch (Except) { 91 } 92 } 93 94 #endif // TEST_HAS_NO_EXCEPTIONS 95 } 96 97 int main(int, char**) { 98 test(); 99 static_assert(test()); 100 testException(); 101 return 0; 102 } 103