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<const G&, E>) expected(const unexpected<G>& e); 13 // 14 // Let GF be const 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<void, int>, const std::unexpected<int>&>); 35 36 // !is_constructible_v<E, GF> 37 struct foo {}; 38 static_assert(!std::is_constructible_v<std::expected<void, int>, const std::unexpected<foo>&>); 39 static_assert(!std::is_constructible_v<std::expected<void, MoveOnly>, const std::unexpected<MoveOnly>&>); 40 41 // explicit(!is_convertible_v<const G&, E>) 42 struct NotConvertible { 43 explicit NotConvertible(int); 44 }; 45 static_assert(std::is_convertible_v<const std::unexpected<int>&, std::expected<void, int>>); 46 static_assert(!std::is_convertible_v<const std::unexpected<int>&, std::expected<void, 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 T> 55 constexpr void testUnexpected() { 56 const std::unexpected<int> u(5); 57 std::expected<void, T> e(u); 58 assert(!e.has_value()); 59 assert(e.error() == 5); 60 } 61 62 constexpr bool test() { 63 testUnexpected<int>(); 64 testUnexpected<MyInt>(); 65 testUnexpected<TailClobberer<1>>(); 66 return true; 67 } 68 69 void testException() { 70 #ifndef TEST_HAS_NO_EXCEPTIONS 71 struct Throwing { 72 Throwing(int) { throw Except{}; } 73 }; 74 75 { 76 const std::unexpected<int> u(5); 77 try { 78 [[maybe_unused]] std::expected<void, Throwing> e(u); 79 assert(false); 80 } catch (Except) { 81 } 82 } 83 84 #endif // TEST_HAS_NO_EXCEPTIONS 85 } 86 87 int main(int, char**) { 88 test(); 89 static_assert(test()); 90 testException(); 91 return 0; 92 } 93