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

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