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 unexpected(in_place_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// Throws: Any exception thrown by the initialization of unex.
19
20#include <cassert>
21#include <concepts>
22#include <expected>
23#include <utility>
24
25#include "test_macros.h"
26
27// Test Constraints:
28static_assert(std::constructible_from<std::unexpected<int>, std::in_place_t, int>);
29
30// !is_constructible_v<E, Args...>
31struct Foo {};
32static_assert(!std::constructible_from<std::unexpected<Foo>, std::in_place_t, int>);
33
34// test explicit
35template <class T>
36void conversion_test(T);
37
38template <class T, class... Args>
39concept ImplicitlyConstructible = requires(Args&&... args) { conversion_test<T>({std::forward<Args>(args)...}); };
40
41static_assert(ImplicitlyConstructible<int, int>);
42static_assert(!ImplicitlyConstructible<std::unexpected<int>, std::in_place_t, int>);
43
44struct Arg {
45 int i;
46 constexpr Arg(int ii) : i(ii) {}
47 constexpr Arg(const Arg& other) : i(other.i) {}
48 constexpr Arg(Arg&& other) : i(other.i) { other.i = 0; }
49};
50
51struct Error {
52 Arg arg;
53 constexpr explicit Error(const Arg& a) : arg(a) {}
54 constexpr explicit Error(Arg&& a) : arg(std::move(a)) {}
55 Error(std::initializer_list<Error>) :arg(0){ assert(false); }
56};
57
58constexpr bool test() {
59 // lvalue
60 {
61 Arg a{5};
62 std::unexpected<Error> unex(std::in_place, a);
63 assert(unex.error().arg.i == 5);
64 assert(a.i == 5);
65 }
66
67 // rvalue
68 {
69 Arg a{5};
70 std::unexpected<Error> unex(std::in_place, std::move(a));
71 assert(unex.error().arg.i == 5);
72 assert(a.i == 0);
73 }
74
75 // Direct-non-list-initializes: does not trigger initializer_list overload
76 {
77 Error e(5);
78 [[maybe_unused]] std::unexpected<Error> unex(std::in_place, e);
79 }
80 return true;
81}
82
83void testException() {
84#ifndef TEST_HAS_NO_EXCEPTIONS
85 struct Except {};
86
87 struct Throwing {
88 Throwing(int) { throw Except{}; }
89 };
90
91 try {
92 std::unexpected<Throwing> u(std::in_place, 5);
93 assert(false);
94 } catch (Except) {
95 }
96#endif // TEST_HAS_NO_EXCEPTIONS
97}
98
99int main(int, char**) {
100 test();
101 static_assert(test());
102 testException();
103 return 0;
104}
105

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