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 Err = E>
12// constexpr explicit unexpected(Err&& e);
13//
14// Constraints:
15// - is_same_v<remove_cvref_t<Err>, unexpected> is false; and
16// - is_same_v<remove_cvref_t<Err>, in_place_t> is false; and
17// - is_constructible_v<E, Err> is true.
18//
19// Effects: Direct-non-list-initializes unex with std::forward<Err>(e).
20// Throws: Any exception thrown by the initialization of unex.
21
22#include <cassert>
23#include <concepts>
24#include <expected>
25#include <utility>
26
27#include "test_macros.h"
28
29// Test Constraints:
30static_assert(std::constructible_from<std::unexpected<int>, int>);
31
32// is_same_v<remove_cvref_t<Err>, unexpected>
33struct CstrFromUnexpected {
34 CstrFromUnexpected(CstrFromUnexpected const&) = delete;
35 CstrFromUnexpected(std::unexpected<CstrFromUnexpected> const&);
36};
37static_assert(!std::constructible_from<std::unexpected<CstrFromUnexpected>, std::unexpected<CstrFromUnexpected>>);
38
39// is_same_v<remove_cvref_t<Err>, in_place_t>
40struct CstrFromInplace {
41 CstrFromInplace(std::in_place_t);
42};
43static_assert(!std::constructible_from<std::unexpected<CstrFromInplace>, std::in_place_t>);
44
45// !is_constructible_v<E, Err>
46struct Foo {};
47static_assert(!std::constructible_from<std::unexpected<Foo>, int>);
48
49// test explicit
50static_assert(std::convertible_to<int, int>);
51static_assert(!std::convertible_to<int, std::unexpected<int>>);
52
53struct Error {
54 int i;
55 constexpr Error(int ii) : i(ii) {}
56 constexpr Error(const Error& other) : i(other.i) {}
57 constexpr Error(Error&& other) : i(other.i) { other.i = 0; }
58 Error(std::initializer_list<Error>) { assert(false); }
59};
60
61constexpr bool test() {
62 // lvalue
63 {
64 Error e(5);
65 std::unexpected<Error> unex(e);
66 assert(unex.error().i == 5);
67 assert(e.i == 5);
68 }
69
70 // rvalue
71 {
72 Error e(5);
73 std::unexpected<Error> unex(std::move(e));
74 assert(unex.error().i == 5);
75 assert(e.i == 0);
76 }
77
78 // Direct-non-list-initializes: does not trigger initializer_list overload
79 {
80 Error e(5);
81 [[maybe_unused]] std::unexpected<Error> unex(e);
82 }
83
84 // Test default template argument.
85 // Without it, the template parameter cannot be deduced from an initializer list
86 {
87 struct Bar {
88 int i;
89 int j;
90 constexpr Bar(int ii, int jj) : i(ii), j(jj) {}
91 };
92 std::unexpected<Bar> ue({5, 6});
93 assert(ue.error().i == 5);
94 assert(ue.error().j == 6);
95 }
96
97 return true;
98}
99
100void testException() {
101#ifndef TEST_HAS_NO_EXCEPTIONS
102 struct Except {};
103
104 struct Throwing {
105 Throwing() = default;
106 Throwing(const Throwing&) { throw Except{}; }
107 };
108
109 Throwing t;
110 try {
111 std::unexpected<Throwing> u(t);
112 assert(false);
113 } catch (Except) {
114 }
115#endif // TEST_HAS_NO_EXCEPTIONS
116}
117
118int main(int, char**) {
119 test();
120 static_assert(test());
121 testException();
122 return 0;
123}
124

source code of libcxx/test/std/utilities/expected/expected.unexpected/ctor/ctor.error.pass.cpp