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 transform(F&&) &;
17 // template<class F> constexpr auto transform(F&&) &&;
18 // template<class F> constexpr auto transform(F&&) const&;
19 // template<class F> constexpr auto transform(F&&) const&&;
20
21 #include "test_macros.h"
22 #include <cassert>
23 #include <optional>
24 #include <type_traits>
25
26 struct LVal {
operator ()LVal27 constexpr int operator()(int&) { return 1; }
28 int operator()(const int&) = delete;
29 int operator()(int&&) = delete;
30 int operator()(const int&&) = delete;
31 };
32
33 struct CLVal {
34 int operator()(int&) = delete;
operator ()CLVal35 constexpr int operator()(const int&) { return 1; }
36 int operator()(int&&) = delete;
37 int operator()(const int&&) = delete;
38 };
39
40 struct RVal {
41 int operator()(int&) = delete;
42 int operator()(const int&) = delete;
operator ()RVal43 constexpr int operator()(int&&) { return 1; }
44 int operator()(const int&&) = delete;
45 };
46
47 struct CRVal {
48 int operator()(int&) = delete;
49 int operator()(const int&) = delete;
50 int operator()(int&&) = delete;
operator ()CRVal51 constexpr int operator()(const int&&) { return 1; }
52 };
53
54 struct RefQual {
operator ()RefQual55 constexpr int operator()(int) & { return 1; }
56 int operator()(int) const& = delete;
57 int operator()(int) && = delete;
58 int operator()(int) const&& = delete;
59 };
60
61 struct CRefQual {
62 int operator()(int) & = delete;
operator ()CRefQual63 constexpr int operator()(int) const& { return 1; }
64 int operator()(int) && = delete;
65 int operator()(int) const&& = delete;
66 };
67
68 struct RVRefQual {
69 int operator()(int) & = delete;
70 int operator()(int) const& = delete;
operator ()RVRefQual71 constexpr int operator()(int) && { return 1; }
72 int operator()(int) const&& = delete;
73 };
74
75 struct RVCRefQual {
76 int operator()(int) & = delete;
77 int operator()(int) const& = delete;
78 int operator()(int) && = delete;
operator ()RVCRefQual79 constexpr int operator()(int) const&& { return 1; }
80 };
81
82 struct NoCopy {
83 NoCopy() = default;
NoCopyNoCopy84 NoCopy(const NoCopy&) { assert(false); }
operator ()NoCopy85 int operator()(const NoCopy&&) { return 1; }
86 };
87
88 struct NoMove {
89 NoMove() = default;
90 NoMove(NoMove&&) = delete;
operator ()NoMove91 NoMove operator()(const NoCopy&&) { return NoMove{}; }
92 };
93
test_val_types()94 constexpr void test_val_types() {
95 // Test & overload
96 {
97 // Without & qualifier on F's operator()
98 {
99 std::optional<int> i{0};
100 assert(i.transform(LVal{}) == 1);
101 ASSERT_SAME_TYPE(decltype(i.transform(LVal{})), std::optional<int>);
102 }
103
104 //With & qualifier on F's operator()
105 {
106 std::optional<int> i{0};
107 RefQual l{};
108 assert(i.transform(l) == 1);
109 ASSERT_SAME_TYPE(decltype(i.transform(l)), std::optional<int>);
110 }
111 }
112
113 // Test const& overload
114 {
115 // Without & qualifier on F's operator()
116 {
117 const std::optional<int> i{0};
118 assert(i.transform(CLVal{}) == 1);
119 ASSERT_SAME_TYPE(decltype(i.transform(CLVal{})), std::optional<int>);
120 }
121
122 //With & qualifier on F's operator()
123 {
124 const std::optional<int> i{0};
125 const CRefQual l{};
126 assert(i.transform(l) == 1);
127 ASSERT_SAME_TYPE(decltype(i.transform(l)), std::optional<int>);
128 }
129 }
130
131 // Test && overload
132 {
133 // Without & qualifier on F's operator()
134 {
135 std::optional<int> i{0};
136 assert(std::move(i).transform(RVal{}) == 1);
137 ASSERT_SAME_TYPE(decltype(std::move(i).transform(RVal{})), std::optional<int>);
138 }
139
140 //With & qualifier on F's operator()
141 {
142 std::optional<int> i{0};
143 assert(i.transform(RVRefQual{}) == 1);
144 ASSERT_SAME_TYPE(decltype(i.transform(RVRefQual{})), std::optional<int>);
145 }
146 }
147
148 // Test const&& overload
149 {
150 // Without & qualifier on F's operator()
151 {
152 const std::optional<int> i{0};
153 assert(std::move(i).transform(CRVal{}) == 1);
154 ASSERT_SAME_TYPE(decltype(std::move(i).transform(CRVal{})), std::optional<int>);
155 }
156
157 //With & qualifier on F's operator()
158 {
159 const std::optional<int> i{0};
160 const RVCRefQual l{};
161 assert(i.transform(std::move(l)) == 1);
162 ASSERT_SAME_TYPE(decltype(i.transform(std::move(l))), std::optional<int>);
163 }
164 }
165 }
166
167 struct NonConst {
non_constNonConst168 int non_const() { return 1; }
169 };
170
171 // check that the lambda body is not instantiated during overload resolution
test_sfinae()172 constexpr void test_sfinae() {
173 std::optional<NonConst> opt{};
174 auto l = [](auto&& x) { return x.non_const(); };
175 opt.transform(l);
176 std::move(opt).transform(l);
177 }
178
test()179 constexpr bool test() {
180 test_sfinae();
181 test_val_types();
182 std::optional<int> opt;
183 const auto& copt = opt;
184
185 const auto never_called = [](int) {
186 assert(false);
187 return 0;
188 };
189
190 opt.transform(never_called);
191 std::move(opt).transform(never_called);
192 copt.transform(never_called);
193 std::move(copt).transform(never_called);
194
195 std::optional<NoCopy> nc;
196 const auto& cnc = nc;
197 std::move(nc).transform(NoCopy{});
198 std::move(cnc).transform(NoCopy{});
199
200 std::move(nc).transform(NoMove{});
201 std::move(cnc).transform(NoMove{});
202
203 return true;
204 }
205
main(int,char **)206 int main(int, char**) {
207 test();
208 static_assert(test());
209 return 0;
210 }
211