1//===----------------------------------------------------------------------===//
2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3// See https://llvm.org/LICENSE.txt for license information.
4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5//
6//===----------------------------------------------------------------------===//
7
8// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
9
10// template<class... Args>
11// constexpr explicit unexpected(in_place_t, Args&&... args);
12//
13// Constraints: is_constructible_v<E, Args...> is true.
14//
15// Effects: Direct-non-list-initializes unex with std::forward<Args>(args)....
16//
17// Throws: Any exception thrown by the initialization of unex.
18
19#include <cassert>
20#include <concepts>
21#include <expected>
22#include <utility>
23
24#include "test_macros.h"
25
26// Test Constraints:
27static_assert(std::constructible_from<std::unexpected<int>, std::in_place_t, int>);
28
29// !is_constructible_v<E, Args...>
30struct Foo {};
31static_assert(!std::constructible_from<std::unexpected<Foo>, std::in_place_t, int>);
32
33// test explicit
34template <class T>
35void conversion_test(T);
36
37template <class T, class... Args>
38concept ImplicitlyConstructible = requires(Args&&... args) { conversion_test<T>({std::forward<Args>(args)...}); };
39
40static_assert(ImplicitlyConstructible<int, int>);
41static_assert(!ImplicitlyConstructible<std::unexpected<int>, std::in_place_t, int>);
42
43struct Arg {
44 int i;
45 constexpr Arg(int ii) : i(ii) {}
46 constexpr Arg(const Arg& other) : i(other.i) {}
47 constexpr Arg(Arg&& other) : i(other.i) { other.i = 0; }
48};
49
50struct Error {
51 Arg arg;
52 constexpr explicit Error(const Arg& a) : arg(a) {}
53 constexpr explicit Error(Arg&& a) : arg(std::move(a)) {}
54 Error(std::initializer_list<Error>) :arg(0){ assert(false); }
55};
56
57constexpr bool test() {
58 // lvalue
59 {
60 Arg a{5};
61 std::unexpected<Error> unex(std::in_place, a);
62 assert(unex.error().arg.i == 5);
63 assert(a.i == 5);
64 }
65
66 // rvalue
67 {
68 Arg a{5};
69 std::unexpected<Error> unex(std::in_place, std::move(a));
70 assert(unex.error().arg.i == 5);
71 assert(a.i == 0);
72 }
73
74 // Direct-non-list-initializes: does not trigger initializer_list overload
75 {
76 Error e(5);
77 [[maybe_unused]] std::unexpected<Error> unex(std::in_place, e);
78 }
79 return true;
80}
81
82void testException() {
83#ifndef TEST_HAS_NO_EXCEPTIONS
84 struct Except {};
85
86 struct Throwing {
87 Throwing(int) { throw Except{}; }
88 };
89
90 try {
91 std::unexpected<Throwing> u(std::in_place, 5);
92 assert(false);
93 } catch (Except) {
94 }
95#endif // TEST_HAS_NO_EXCEPTIONS
96}
97
98int main(int, char**) {
99 test();
100 static_assert(test());
101 testException();
102 return 0;
103}
104

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