Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / libcxx / test / std / utilities / optional / optional.monadic / and_then.pass.cpp
blob375820a9033d9c246cc2e565d2ebe965b52c6fe5
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 //===----------------------------------------------------------------------===//
9 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
11 // XFAIL: availability-bad_optional_access-missing && !no-exceptions
13 // <optional>
15 // template<class F> constexpr auto and_then(F&&) &;
16 // template<class F> constexpr auto and_then(F&&) &&;
17 // template<class F> constexpr auto and_then(F&&) const&;
18 // template<class F> constexpr auto and_then(F&&) const&&;
20 #include <cassert>
21 #include <optional>
23 #include "test_macros.h"
25 struct LVal {
26 constexpr std::optional<int> operator()(int&) { return 1; }
27 std::optional<int> operator()(const int&) = delete;
28 std::optional<int> operator()(int&&) = delete;
29 std::optional<int> operator()(const int&&) = delete;
32 struct CLVal {
33 std::optional<int> operator()(int&) = delete;
34 constexpr std::optional<int> operator()(const int&) { return 1; }
35 std::optional<int> operator()(int&&) = delete;
36 std::optional<int> operator()(const int&&) = delete;
39 struct RVal {
40 std::optional<int> operator()(int&) = delete;
41 std::optional<int> operator()(const int&) = delete;
42 constexpr std::optional<int> operator()(int&&) { return 1; }
43 std::optional<int> operator()(const int&&) = delete;
46 struct CRVal {
47 std::optional<int> operator()(int&) = delete;
48 std::optional<int> operator()(const int&) = delete;
49 std::optional<int> operator()(int&&) = delete;
50 constexpr std::optional<int> operator()(const int&&) { return 1; }
53 struct RefQual {
54 constexpr std::optional<int> operator()(int) & { return 1; }
55 std::optional<int> operator()(int) const& = delete;
56 std::optional<int> operator()(int) && = delete;
57 std::optional<int> operator()(int) const&& = delete;
60 struct CRefQual {
61 std::optional<int> operator()(int) & = delete;
62 constexpr std::optional<int> operator()(int) const& { return 1; }
63 std::optional<int> operator()(int) && = delete;
64 std::optional<int> operator()(int) const&& = delete;
67 struct RVRefQual {
68 std::optional<int> operator()(int) & = delete;
69 std::optional<int> operator()(int) const& = delete;
70 constexpr std::optional<int> operator()(int) && { return 1; }
71 std::optional<int> operator()(int) const&& = delete;
74 struct RVCRefQual {
75 std::optional<int> operator()(int) & = delete;
76 std::optional<int> operator()(int) const& = delete;
77 std::optional<int> operator()(int) && = delete;
78 constexpr std::optional<int> operator()(int) const&& { return 1; }
81 struct NOLVal {
82 constexpr std::optional<int> operator()(int&) { return std::nullopt; }
83 std::optional<int> operator()(const int&) = delete;
84 std::optional<int> operator()(int&&) = delete;
85 std::optional<int> operator()(const int&&) = delete;
88 struct NOCLVal {
89 std::optional<int> operator()(int&) = delete;
90 constexpr std::optional<int> operator()(const int&) { return std::nullopt; }
91 std::optional<int> operator()(int&&) = delete;
92 std::optional<int> operator()(const int&&) = delete;
95 struct NORVal {
96 std::optional<int> operator()(int&) = delete;
97 std::optional<int> operator()(const int&) = delete;
98 constexpr std::optional<int> operator()(int&&) { return std::nullopt; }
99 std::optional<int> operator()(const int&&) = delete;
102 struct NOCRVal {
103 std::optional<int> operator()(int&) = delete;
104 std::optional<int> operator()(const int&) = delete;
105 std::optional<int> operator()(int&&) = delete;
106 constexpr std::optional<int> operator()(const int&&) { return std::nullopt; }
109 struct NORefQual {
110 constexpr std::optional<int> operator()(int) & { return std::nullopt; }
111 std::optional<int> operator()(int) const& = delete;
112 std::optional<int> operator()(int) && = delete;
113 std::optional<int> operator()(int) const&& = delete;
116 struct NOCRefQual {
117 std::optional<int> operator()(int) & = delete;
118 constexpr std::optional<int> operator()(int) const& { return std::nullopt; }
119 std::optional<int> operator()(int) && = delete;
120 std::optional<int> operator()(int) const&& = delete;
123 struct NORVRefQual {
124 std::optional<int> operator()(int) & = delete;
125 std::optional<int> operator()(int) const& = delete;
126 constexpr std::optional<int> operator()(int) && { return std::nullopt; }
127 std::optional<int> operator()(int) const&& = delete;
130 struct NORVCRefQual {
131 std::optional<int> operator()(int) & = delete;
132 std::optional<int> operator()(int) const& = delete;
133 std::optional<int> operator()(int) && = delete;
134 constexpr std::optional<int> operator()(int) const&& { return std::nullopt; }
137 struct NoCopy {
138 NoCopy() = default;
139 NoCopy(const NoCopy&) { assert(false); }
140 std::optional<int> operator()(const NoCopy&&) { return 1; }
143 struct NonConst {
144 std::optional<int> non_const() { return 1; }
147 constexpr void test_val_types() {
148 // Test & overload
150 // Without & qualifier on F's operator()
152 std::optional<int> i{0};
153 assert(i.and_then(LVal{}) == 1);
154 assert(i.and_then(NOLVal{}) == std::nullopt);
155 ASSERT_SAME_TYPE(decltype(i.and_then(LVal{})), std::optional<int>);
158 //With & qualifier on F's operator()
160 std::optional<int> i{0};
161 RefQual l{};
162 assert(i.and_then(l) == 1);
163 NORefQual nl{};
164 assert(i.and_then(nl) == std::nullopt);
165 ASSERT_SAME_TYPE(decltype(i.and_then(l)), std::optional<int>);
169 // Test const& overload
171 // Without & qualifier on F's operator()
173 const std::optional<int> i{0};
174 assert(i.and_then(CLVal{}) == 1);
175 assert(i.and_then(NOCLVal{}) == std::nullopt);
176 ASSERT_SAME_TYPE(decltype(i.and_then(CLVal{})), std::optional<int>);
179 //With & qualifier on F's operator()
181 const std::optional<int> i{0};
182 const CRefQual l{};
183 assert(i.and_then(l) == 1);
184 const NOCRefQual nl{};
185 assert(i.and_then(nl) == std::nullopt);
186 ASSERT_SAME_TYPE(decltype(i.and_then(l)), std::optional<int>);
190 // Test && overload
192 // Without & qualifier on F's operator()
194 std::optional<int> i{0};
195 assert(std::move(i).and_then(RVal{}) == 1);
196 assert(std::move(i).and_then(NORVal{}) == std::nullopt);
197 ASSERT_SAME_TYPE(decltype(std::move(i).and_then(RVal{})), std::optional<int>);
200 //With & qualifier on F's operator()
202 std::optional<int> i{0};
203 assert(i.and_then(RVRefQual{}) == 1);
204 assert(i.and_then(NORVRefQual{}) == std::nullopt);
205 ASSERT_SAME_TYPE(decltype(i.and_then(RVRefQual{})), std::optional<int>);
209 // Test const&& overload
211 // Without & qualifier on F's operator()
213 const std::optional<int> i{0};
214 assert(std::move(i).and_then(CRVal{}) == 1);
215 assert(std::move(i).and_then(NOCRVal{}) == std::nullopt);
216 ASSERT_SAME_TYPE(decltype(std::move(i).and_then(CRVal{})), std::optional<int>);
219 //With & qualifier on F's operator()
221 const std::optional<int> i{0};
222 const RVCRefQual l{};
223 assert(i.and_then(std::move(l)) == 1);
224 const NORVCRefQual nl{};
225 assert(i.and_then(std::move(nl)) == std::nullopt);
226 ASSERT_SAME_TYPE(decltype(i.and_then(std::move(l))), std::optional<int>);
231 // check that the lambda body is not instantiated during overload resolution
232 constexpr void test_sfinae() {
233 std::optional<NonConst> opt{};
234 auto l = [](auto&& x) { return x.non_const(); };
235 opt.and_then(l);
236 std::move(opt).and_then(l);
239 constexpr bool test() {
240 test_val_types();
241 std::optional<int> opt{};
242 const auto& copt = opt;
244 const auto never_called = [](int) {
245 assert(false);
246 return std::optional<int>{};
249 opt.and_then(never_called);
250 std::move(opt).and_then(never_called);
251 copt.and_then(never_called);
252 std::move(copt).and_then(never_called);
254 std::optional<NoCopy> nc;
255 const auto& cnc = nc;
256 std::move(cnc).and_then(NoCopy{});
257 std::move(nc).and_then(NoCopy{});
259 return true;
262 int main(int, char**) {
263 test();
264 static_assert(test());
265 return 0;