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