xref: /llvm-project/libcxx/test/std/utilities/expected/expected.expected/ctor/ctor.unexpect.pass.cpp (revision 6a54dfbfe534276d644d7f9c027f0deeb748dd53)
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... Args>
12 //   constexpr explicit expected(unexpect_t, Args&&... args);
13 //
14 // Constraints: is_constructible_v<E, Args...> is true.
15 //
16 // Effects: Direct-non-list-initializes unex with std::forward<Args>(args)....
17 //
18 // Postconditions: has_value() is false.
19 //
20 // Throws: Any exception thrown by the initialization of unex.
21 
22 #include <cassert>
23 #include <expected>
24 #include <tuple>
25 #include <type_traits>
26 #include <utility>
27 
28 #include "MoveOnly.h"
29 #include "test_macros.h"
30 #include "../../types.h"
31 
32 // Test Constraints:
33 static_assert(std::is_constructible_v<std::expected<int, int>, std::unexpect_t>);
34 static_assert(std::is_constructible_v<std::expected<int, int>, std::unexpect_t, int>);
35 
36 // !is_constructible_v<T, Args...>
37 struct foo {};
38 static_assert(!std::is_constructible_v<std::expected<int, foo>, std::unexpect_t, int>);
39 
40 // test explicit
41 template <class T>
42 void conversion_test(T);
43 
44 template <class T, class... Args>
45 concept ImplicitlyConstructible = requires(Args&&... args) { conversion_test<T>({std::forward<Args>(args)...}); };
46 static_assert(ImplicitlyConstructible<int, int>);
47 
48 static_assert(!ImplicitlyConstructible<std::expected<int, int>, std::unexpect_t>);
49 static_assert(!ImplicitlyConstructible<std::expected<int, int>, std::unexpect_t, int>);
50 
51 struct CopyOnly {
52   int i;
53   constexpr CopyOnly(int ii) : i(ii) {}
54   CopyOnly(const CopyOnly&) = default;
55   CopyOnly(CopyOnly&&)      = delete;
56   friend constexpr bool operator==(const CopyOnly& mi, int ii) { return mi.i == ii; }
57 };
58 
59 template <class T, class V = int>
60 constexpr void testInt() {
61   std::expected<V, T> e(std::unexpect, 5);
62   assert(!e.has_value());
63   assert(e.error() == 5);
64 }
65 
66 template <class T, class V = int>
67 constexpr void testLValue() {
68   T t(5);
69   std::expected<V, T> e(std::unexpect, t);
70   assert(!e.has_value());
71   assert(e.error() == 5);
72 }
73 
74 template <class T, class V = int>
75 constexpr void testRValue() {
76   std::expected<V, T> e(std::unexpect, T(5));
77   assert(!e.has_value());
78   assert(e.error() == 5);
79 }
80 
81 constexpr bool test() {
82   testInt<int>();
83   testInt<CopyOnly>();
84   testInt<MoveOnly>();
85   testInt<TailClobberer<1>, bool>();
86   testLValue<int>();
87   testLValue<CopyOnly>();
88   testLValue<TailClobberer<1>, bool>();
89   testRValue<int>();
90   testRValue<MoveOnly>();
91   testRValue<TailClobberer<1>, bool>();
92 
93   // no arg
94   {
95     std::expected<int, int> e(std::unexpect);
96     assert(!e.has_value());
97     assert(e.error() == 0);
98   }
99 
100   // one arg
101   {
102     std::expected<int, int> e(std::unexpect, 5);
103     assert(!e.has_value());
104     assert(e.error() == 5);
105   }
106 
107   // multi args
108   {
109     std::expected<int, std::tuple<int, short, MoveOnly>> e(std::unexpect, 1, short{2}, MoveOnly(3));
110     assert(!e.has_value());
111     assert((e.error() == std::tuple<int, short, MoveOnly>(1, short{2}, MoveOnly(3))));
112   }
113 
114   return true;
115 }
116 
117 void testException() {
118 #ifndef TEST_HAS_NO_EXCEPTIONS
119   struct Throwing {
120     Throwing(int) { throw Except{}; };
121   };
122 
123   try {
124     std::expected<int, Throwing> u(std::unexpect, 5);
125     assert(false);
126   } catch (Except) {
127   }
128 #endif // TEST_HAS_NO_EXCEPTIONS
129 }
130 
131 int main(int, char**) {
132   test();
133   static_assert(test());
134   testException();
135   return 0;
136 }
137