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 // Throwing bad_optional_access is supported starting in macosx10.13
12 // XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11|12}} && !no-exceptions
13
14 // <optional>
15
16 // template<class F> constexpr auto and_then(F&&) &;
17 // template<class F> constexpr auto and_then(F&&) &&;
18 // template<class F> constexpr auto and_then(F&&) const&;
19 // template<class F> constexpr auto and_then(F&&) const&&;
20
21 #include <cassert>
22 #include <optional>
23
24 #include "test_macros.h"
25
26 struct LVal {
operator ()LVal27 constexpr std::optional<int> operator()(int&) { return 1; }
28 std::optional<int> operator()(const int&) = delete;
29 std::optional<int> operator()(int&&) = delete;
30 std::optional<int> operator()(const int&&) = delete;
31 };
32
33 struct CLVal {
34 std::optional<int> operator()(int&) = delete;
operator ()CLVal35 constexpr std::optional<int> operator()(const int&) { return 1; }
36 std::optional<int> operator()(int&&) = delete;
37 std::optional<int> operator()(const int&&) = delete;
38 };
39
40 struct RVal {
41 std::optional<int> operator()(int&) = delete;
42 std::optional<int> operator()(const int&) = delete;
operator ()RVal43 constexpr std::optional<int> operator()(int&&) { return 1; }
44 std::optional<int> operator()(const int&&) = delete;
45 };
46
47 struct CRVal {
48 std::optional<int> operator()(int&) = delete;
49 std::optional<int> operator()(const int&) = delete;
50 std::optional<int> operator()(int&&) = delete;
operator ()CRVal51 constexpr std::optional<int> operator()(const int&&) { return 1; }
52 };
53
54 struct RefQual {
operator ()RefQual55 constexpr std::optional<int> operator()(int) & { return 1; }
56 std::optional<int> operator()(int) const& = delete;
57 std::optional<int> operator()(int) && = delete;
58 std::optional<int> operator()(int) const&& = delete;
59 };
60
61 struct CRefQual {
62 std::optional<int> operator()(int) & = delete;
operator ()CRefQual63 constexpr std::optional<int> operator()(int) const& { return 1; }
64 std::optional<int> operator()(int) && = delete;
65 std::optional<int> operator()(int) const&& = delete;
66 };
67
68 struct RVRefQual {
69 std::optional<int> operator()(int) & = delete;
70 std::optional<int> operator()(int) const& = delete;
operator ()RVRefQual71 constexpr std::optional<int> operator()(int) && { return 1; }
72 std::optional<int> operator()(int) const&& = delete;
73 };
74
75 struct RVCRefQual {
76 std::optional<int> operator()(int) & = delete;
77 std::optional<int> operator()(int) const& = delete;
78 std::optional<int> operator()(int) && = delete;
operator ()RVCRefQual79 constexpr std::optional<int> operator()(int) const&& { return 1; }
80 };
81
82 struct NOLVal {
operator ()NOLVal83 constexpr std::optional<int> operator()(int&) { return std::nullopt; }
84 std::optional<int> operator()(const int&) = delete;
85 std::optional<int> operator()(int&&) = delete;
86 std::optional<int> operator()(const int&&) = delete;
87 };
88
89 struct NOCLVal {
90 std::optional<int> operator()(int&) = delete;
operator ()NOCLVal91 constexpr std::optional<int> operator()(const int&) { return std::nullopt; }
92 std::optional<int> operator()(int&&) = delete;
93 std::optional<int> operator()(const int&&) = delete;
94 };
95
96 struct NORVal {
97 std::optional<int> operator()(int&) = delete;
98 std::optional<int> operator()(const int&) = delete;
operator ()NORVal99 constexpr std::optional<int> operator()(int&&) { return std::nullopt; }
100 std::optional<int> operator()(const int&&) = delete;
101 };
102
103 struct NOCRVal {
104 std::optional<int> operator()(int&) = delete;
105 std::optional<int> operator()(const int&) = delete;
106 std::optional<int> operator()(int&&) = delete;
operator ()NOCRVal107 constexpr std::optional<int> operator()(const int&&) { return std::nullopt; }
108 };
109
110 struct NORefQual {
operator ()NORefQual111 constexpr std::optional<int> operator()(int) & { return std::nullopt; }
112 std::optional<int> operator()(int) const& = delete;
113 std::optional<int> operator()(int) && = delete;
114 std::optional<int> operator()(int) const&& = delete;
115 };
116
117 struct NOCRefQual {
118 std::optional<int> operator()(int) & = delete;
operator ()NOCRefQual119 constexpr std::optional<int> operator()(int) const& { return std::nullopt; }
120 std::optional<int> operator()(int) && = delete;
121 std::optional<int> operator()(int) const&& = delete;
122 };
123
124 struct NORVRefQual {
125 std::optional<int> operator()(int) & = delete;
126 std::optional<int> operator()(int) const& = delete;
operator ()NORVRefQual127 constexpr std::optional<int> operator()(int) && { return std::nullopt; }
128 std::optional<int> operator()(int) const&& = delete;
129 };
130
131 struct NORVCRefQual {
132 std::optional<int> operator()(int) & = delete;
133 std::optional<int> operator()(int) const& = delete;
134 std::optional<int> operator()(int) && = delete;
operator ()NORVCRefQual135 constexpr std::optional<int> operator()(int) const&& { return std::nullopt; }
136 };
137
138 struct NoCopy {
139 NoCopy() = default;
NoCopyNoCopy140 NoCopy(const NoCopy&) { assert(false); }
operator ()NoCopy141 std::optional<int> operator()(const NoCopy&&) { return 1; }
142 };
143
144 struct NonConst {
non_constNonConst145 std::optional<int> non_const() { return 1; }
146 };
147
test_val_types()148 constexpr void test_val_types() {
149 // Test & overload
150 {
151 // Without & qualifier on F's operator()
152 {
153 std::optional<int> i{0};
154 assert(i.and_then(LVal{}) == 1);
155 assert(i.and_then(NOLVal{}) == std::nullopt);
156 ASSERT_SAME_TYPE(decltype(i.and_then(LVal{})), std::optional<int>);
157 }
158
159 //With & qualifier on F's operator()
160 {
161 std::optional<int> i{0};
162 RefQual l{};
163 assert(i.and_then(l) == 1);
164 NORefQual nl{};
165 assert(i.and_then(nl) == std::nullopt);
166 ASSERT_SAME_TYPE(decltype(i.and_then(l)), std::optional<int>);
167 }
168 }
169
170 // Test const& overload
171 {
172 // Without & qualifier on F's operator()
173 {
174 const std::optional<int> i{0};
175 assert(i.and_then(CLVal{}) == 1);
176 assert(i.and_then(NOCLVal{}) == std::nullopt);
177 ASSERT_SAME_TYPE(decltype(i.and_then(CLVal{})), std::optional<int>);
178 }
179
180 //With & qualifier on F's operator()
181 {
182 const std::optional<int> i{0};
183 const CRefQual l{};
184 assert(i.and_then(l) == 1);
185 const NOCRefQual nl{};
186 assert(i.and_then(nl) == std::nullopt);
187 ASSERT_SAME_TYPE(decltype(i.and_then(l)), std::optional<int>);
188 }
189 }
190
191 // Test && overload
192 {
193 // Without & qualifier on F's operator()
194 {
195 std::optional<int> i{0};
196 assert(std::move(i).and_then(RVal{}) == 1);
197 assert(std::move(i).and_then(NORVal{}) == std::nullopt);
198 ASSERT_SAME_TYPE(decltype(std::move(i).and_then(RVal{})), std::optional<int>);
199 }
200
201 //With & qualifier on F's operator()
202 {
203 std::optional<int> i{0};
204 assert(i.and_then(RVRefQual{}) == 1);
205 assert(i.and_then(NORVRefQual{}) == std::nullopt);
206 ASSERT_SAME_TYPE(decltype(i.and_then(RVRefQual{})), std::optional<int>);
207 }
208 }
209
210 // Test const&& overload
211 {
212 // Without & qualifier on F's operator()
213 {
214 const std::optional<int> i{0};
215 assert(std::move(i).and_then(CRVal{}) == 1);
216 assert(std::move(i).and_then(NOCRVal{}) == std::nullopt);
217 ASSERT_SAME_TYPE(decltype(std::move(i).and_then(CRVal{})), std::optional<int>);
218 }
219
220 //With & qualifier on F's operator()
221 {
222 const std::optional<int> i{0};
223 const RVCRefQual l{};
224 assert(i.and_then(std::move(l)) == 1);
225 const NORVCRefQual nl{};
226 assert(i.and_then(std::move(nl)) == std::nullopt);
227 ASSERT_SAME_TYPE(decltype(i.and_then(std::move(l))), std::optional<int>);
228 }
229 }
230 }
231
232 // check that the lambda body is not instantiated during overload resolution
test_sfinae()233 constexpr void test_sfinae() {
234 std::optional<NonConst> opt{};
235 auto l = [](auto&& x) { return x.non_const(); };
236 opt.and_then(l);
237 std::move(opt).and_then(l);
238 }
239
test()240 constexpr bool test() {
241 test_val_types();
242 std::optional<int> opt{};
243 const auto& copt = opt;
244
245 const auto never_called = [](int) {
246 assert(false);
247 return std::optional<int>{};
248 };
249
250 opt.and_then(never_called);
251 std::move(opt).and_then(never_called);
252 copt.and_then(never_called);
253 std::move(copt).and_then(never_called);
254
255 std::optional<NoCopy> nc;
256 const auto& cnc = nc;
257 std::move(cnc).and_then(NoCopy{});
258 std::move(nc).and_then(NoCopy{});
259
260 return true;
261 }
262
main(int,char **)263 int main(int, char**) {
264 test();
265 static_assert(test());
266 return 0;
267 }
268