@@ -152,6 +152,145 @@ TEST_CASE("Monadic operations", "[monadic]") {
152152#endif
153153 }
154154
155+ SECTION (" transform" ) { // lhs is empty
156+ tl::optional<int > o1;
157+ auto o1r = o1.transform ([](int i) { return i + 2 ; });
158+ STATIC_REQUIRE ((std::is_same<decltype (o1r), tl::optional<int >>::value));
159+ REQUIRE (!o1r);
160+
161+ // lhs has value
162+ tl::optional<int > o2 = 40 ;
163+ auto o2r = o2.transform ([](int i) { return i + 2 ; });
164+ STATIC_REQUIRE ((std::is_same<decltype (o2r), tl::optional<int >>::value));
165+ REQUIRE (o2r.value () == 42 );
166+
167+ struct rval_call_transform {
168+ double operator ()(int ) && { return 42.0 ; };
169+ };
170+
171+ // ensure that function object is forwarded
172+ tl::optional<int > o3 = 42 ;
173+ auto o3r = o3.transform (rval_call_transform{});
174+ STATIC_REQUIRE ((std::is_same<decltype (o3r), tl::optional<double >>::value));
175+ REQUIRE (o3r.value () == 42 );
176+
177+ // ensure that lhs is forwarded
178+ tl::optional<int > o4 = 40 ;
179+ auto o4r = std::move (o4).transform ([](int && i) { return i + 2 ; });
180+ STATIC_REQUIRE ((std::is_same<decltype (o4r), tl::optional<int >>::value));
181+ REQUIRE (o4r.value () == 42 );
182+
183+ // ensure that lhs is const-propagated
184+ const tl::optional<int > o5 = 40 ;
185+ auto o5r = o5.transform ([](const int & i) { return i + 2 ; });
186+ STATIC_REQUIRE ((std::is_same<decltype (o5r), tl::optional<int >>::value));
187+ REQUIRE (o5r.value () == 42 );
188+
189+ // test void return
190+ tl::optional<int > o7 = 40 ;
191+ auto f7 = [](const int & i) { return ; };
192+ auto o7r = o7.transform (f7);
193+ STATIC_REQUIRE (
194+ (std::is_same<decltype (o7r), tl::optional<tl::monostate>>::value));
195+ REQUIRE (o7r.has_value ());
196+
197+ // test each overload in turn
198+ tl::optional<int > o8 = 42 ;
199+ auto o8r = o8.transform ([](int ) { return 42 ; });
200+ REQUIRE (*o8r == 42 );
201+
202+ tl::optional<int > o9 = 42 ;
203+ auto o9r = o9.transform ([](int ) { return ; });
204+ REQUIRE (o9r);
205+
206+ tl::optional<int > o12 = 42 ;
207+ auto o12r = std::move (o12).transform ([](int ) { return 42 ; });
208+ REQUIRE (*o12r == 42 );
209+
210+ tl::optional<int > o13 = 42 ;
211+ auto o13r = std::move (o13).transform ([](int ) { return ; });
212+ REQUIRE (o13r);
213+
214+ const tl::optional<int > o16 = 42 ;
215+ auto o16r = o16.transform ([](int ) { return 42 ; });
216+ REQUIRE (*o16r == 42 );
217+
218+ const tl::optional<int > o17 = 42 ;
219+ auto o17r = o17.transform ([](int ) { return ; });
220+ REQUIRE (o17r);
221+
222+ const tl::optional<int > o20 = 42 ;
223+ auto o20r = std::move (o20).transform ([](int ) { return 42 ; });
224+ REQUIRE (*o20r == 42 );
225+
226+ const tl::optional<int > o21 = 42 ;
227+ auto o21r = std::move (o21).transform ([](int ) { return ; });
228+ REQUIRE (o21r);
229+
230+ tl::optional<int > o24 = tl::nullopt ;
231+ auto o24r = o24.transform ([](int ) { return 42 ; });
232+ REQUIRE (!o24r);
233+
234+ tl::optional<int > o25 = tl::nullopt ;
235+ auto o25r = o25.transform ([](int ) { return ; });
236+ REQUIRE (!o25r);
237+
238+ tl::optional<int > o28 = tl::nullopt ;
239+ auto o28r = std::move (o28).transform ([](int ) { return 42 ; });
240+ REQUIRE (!o28r);
241+
242+ tl::optional<int > o29 = tl::nullopt ;
243+ auto o29r = std::move (o29).transform ([](int ) { return ; });
244+ REQUIRE (!o29r);
245+
246+ const tl::optional<int > o32 = tl::nullopt ;
247+ auto o32r = o32.transform ([](int ) { return 42 ; });
248+ REQUIRE (!o32r);
249+
250+ const tl::optional<int > o33 = tl::nullopt ;
251+ auto o33r = o33.transform ([](int ) { return ; });
252+ REQUIRE (!o33r);
253+
254+ const tl::optional<int > o36 = tl::nullopt ;
255+ auto o36r = std::move (o36).transform ([](int ) { return 42 ; });
256+ REQUIRE (!o36r);
257+
258+ const tl::optional<int > o37 = tl::nullopt ;
259+ auto o37r = std::move (o37).transform ([](int ) { return ; });
260+ REQUIRE (!o37r);
261+
262+ // callable which returns a reference
263+ tl::optional<int > o38 = 42 ;
264+ auto o38r = o38.transform ([](int & i) -> const int & { return i; });
265+ REQUIRE (o38r);
266+ REQUIRE (*o38r == 42 );
267+
268+ int i = 42 ;
269+ tl::optional<int &> o39 = i;
270+ o39.transform ([](int & x) {x = 12 ; });
271+ REQUIRE (i == 12 );
272+ }
273+
274+ SECTION (" transform constexpr" ) {
275+ #if !defined(_MSC_VER) && defined(TL_OPTIONAL_CXX14)
276+ // test each overload in turn
277+ constexpr tl::optional<int > o16 = 42 ;
278+ constexpr auto o16r = o16.transform (get_int);
279+ STATIC_REQUIRE (*o16r == 42 );
280+
281+ constexpr tl::optional<int > o20 = 42 ;
282+ constexpr auto o20r = std::move (o20).transform (get_int);
283+ STATIC_REQUIRE (*o20r == 42 );
284+
285+ constexpr tl::optional<int > o32 = tl::nullopt ;
286+ constexpr auto o32r = o32.transform (get_int);
287+ STATIC_REQUIRE (!o32r);
288+ constexpr tl::optional<int > o36 = tl::nullopt ;
289+ constexpr auto o36r = std::move (o36).transform (get_int);
290+ STATIC_REQUIRE (!o36r);
291+ #endif
292+ }
293+
155294 SECTION (" and_then" ) {
156295
157296 // lhs is empty
0 commit comments