xref: /llvm-project/libcxx/test/std/utilities/optional/optional.monadic/transform.pass.cpp (revision ec350ad418a24f70c88758259c774a1e11c06d74)
117cfc57dSNikolas Klauser //===----------------------------------------------------------------------===//
217cfc57dSNikolas Klauser //
317cfc57dSNikolas Klauser // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
417cfc57dSNikolas Klauser // See https://llvm.org/LICENSE.txt for license information.
517cfc57dSNikolas Klauser // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
617cfc57dSNikolas Klauser //
717cfc57dSNikolas Klauser //===----------------------------------------------------------------------===//
817cfc57dSNikolas Klauser 
917cfc57dSNikolas Klauser // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
10*fd4cc870SLouis Dionne 
1117cfc57dSNikolas Klauser // <optional>
1217cfc57dSNikolas Klauser 
1317cfc57dSNikolas Klauser // template<class F> constexpr auto transform(F&&) &;
1417cfc57dSNikolas Klauser // template<class F> constexpr auto transform(F&&) &&;
1517cfc57dSNikolas Klauser // template<class F> constexpr auto transform(F&&) const&;
1617cfc57dSNikolas Klauser // template<class F> constexpr auto transform(F&&) const&&;
1717cfc57dSNikolas Klauser 
1817cfc57dSNikolas Klauser #include "test_macros.h"
1917cfc57dSNikolas Klauser #include <cassert>
2017cfc57dSNikolas Klauser #include <optional>
2117cfc57dSNikolas Klauser #include <type_traits>
2217cfc57dSNikolas Klauser 
2317cfc57dSNikolas Klauser struct LVal {
operator ()LVal2417cfc57dSNikolas Klauser   constexpr int operator()(int&) { return 1; }
2517cfc57dSNikolas Klauser   int operator()(const int&) = delete;
2617cfc57dSNikolas Klauser   int operator()(int&&) = delete;
2717cfc57dSNikolas Klauser   int operator()(const int&&) = delete;
2817cfc57dSNikolas Klauser };
2917cfc57dSNikolas Klauser 
3017cfc57dSNikolas Klauser struct CLVal {
3117cfc57dSNikolas Klauser   int operator()(int&) = delete;
operator ()CLVal3217cfc57dSNikolas Klauser   constexpr int operator()(const int&) { return 1; }
3317cfc57dSNikolas Klauser   int operator()(int&&) = delete;
3417cfc57dSNikolas Klauser   int operator()(const int&&) = delete;
3517cfc57dSNikolas Klauser };
3617cfc57dSNikolas Klauser 
3717cfc57dSNikolas Klauser struct RVal {
3817cfc57dSNikolas Klauser   int operator()(int&) = delete;
3917cfc57dSNikolas Klauser   int operator()(const int&) = delete;
operator ()RVal4017cfc57dSNikolas Klauser   constexpr int operator()(int&&) { return 1; }
4117cfc57dSNikolas Klauser   int operator()(const int&&) = delete;
4217cfc57dSNikolas Klauser };
4317cfc57dSNikolas Klauser 
4417cfc57dSNikolas Klauser struct CRVal {
4517cfc57dSNikolas Klauser   int operator()(int&) = delete;
4617cfc57dSNikolas Klauser   int operator()(const int&) = delete;
4717cfc57dSNikolas Klauser   int operator()(int&&) = delete;
operator ()CRVal4817cfc57dSNikolas Klauser   constexpr int operator()(const int&&) { return 1; }
4917cfc57dSNikolas Klauser };
5017cfc57dSNikolas Klauser 
5117cfc57dSNikolas Klauser struct RefQual {
operator ()RefQual5217cfc57dSNikolas Klauser   constexpr int operator()(int) & { return 1; }
5317cfc57dSNikolas Klauser   int operator()(int) const& = delete;
5417cfc57dSNikolas Klauser   int operator()(int) && = delete;
5517cfc57dSNikolas Klauser   int operator()(int) const&& = delete;
5617cfc57dSNikolas Klauser };
5717cfc57dSNikolas Klauser 
5817cfc57dSNikolas Klauser struct CRefQual {
5917cfc57dSNikolas Klauser   int operator()(int) & = delete;
operator ()CRefQual6017cfc57dSNikolas Klauser   constexpr int operator()(int) const& { return 1; }
6117cfc57dSNikolas Klauser   int operator()(int) && = delete;
6217cfc57dSNikolas Klauser   int operator()(int) const&& = delete;
6317cfc57dSNikolas Klauser };
6417cfc57dSNikolas Klauser 
6517cfc57dSNikolas Klauser struct RVRefQual {
6617cfc57dSNikolas Klauser   int operator()(int) & = delete;
6717cfc57dSNikolas Klauser   int operator()(int) const& = delete;
operator ()RVRefQual6817cfc57dSNikolas Klauser   constexpr int operator()(int) && { return 1; }
6917cfc57dSNikolas Klauser   int operator()(int) const&& = delete;
7017cfc57dSNikolas Klauser };
7117cfc57dSNikolas Klauser 
7217cfc57dSNikolas Klauser struct RVCRefQual {
7317cfc57dSNikolas Klauser   int operator()(int) & = delete;
7417cfc57dSNikolas Klauser   int operator()(int) const& = delete;
7517cfc57dSNikolas Klauser   int operator()(int) && = delete;
operator ()RVCRefQual7617cfc57dSNikolas Klauser   constexpr int operator()(int) const&& { return 1; }
7717cfc57dSNikolas Klauser };
7817cfc57dSNikolas Klauser 
7917cfc57dSNikolas Klauser struct NoCopy {
8017cfc57dSNikolas Klauser   NoCopy() = default;
NoCopyNoCopy8117cfc57dSNikolas Klauser   NoCopy(const NoCopy&) { assert(false); }
operator ()NoCopy8217cfc57dSNikolas Klauser   int operator()(const NoCopy&&) { return 1; }
8317cfc57dSNikolas Klauser };
8417cfc57dSNikolas Klauser 
8517cfc57dSNikolas Klauser struct NoMove {
8617cfc57dSNikolas Klauser   NoMove() = default;
8717cfc57dSNikolas Klauser   NoMove(NoMove&&) = delete;
operator ()NoMove8817cfc57dSNikolas Klauser   NoMove operator()(const NoCopy&&) { return NoMove{}; }
8917cfc57dSNikolas Klauser };
9017cfc57dSNikolas Klauser 
test_val_types()9117cfc57dSNikolas Klauser constexpr void test_val_types() {
9217cfc57dSNikolas Klauser   // Test & overload
9317cfc57dSNikolas Klauser   {
9417cfc57dSNikolas Klauser     // Without & qualifier on F's operator()
9517cfc57dSNikolas Klauser     {
9617cfc57dSNikolas Klauser       std::optional<int> i{0};
9717cfc57dSNikolas Klauser       assert(i.transform(LVal{}) == 1);
9817cfc57dSNikolas Klauser       ASSERT_SAME_TYPE(decltype(i.transform(LVal{})), std::optional<int>);
9917cfc57dSNikolas Klauser     }
10017cfc57dSNikolas Klauser 
10117cfc57dSNikolas Klauser     //With & qualifier on F's operator()
10217cfc57dSNikolas Klauser     {
10317cfc57dSNikolas Klauser       std::optional<int> i{0};
10417cfc57dSNikolas Klauser       RefQual l{};
10517cfc57dSNikolas Klauser       assert(i.transform(l) == 1);
10617cfc57dSNikolas Klauser       ASSERT_SAME_TYPE(decltype(i.transform(l)), std::optional<int>);
10717cfc57dSNikolas Klauser     }
10817cfc57dSNikolas Klauser   }
10917cfc57dSNikolas Klauser 
11017cfc57dSNikolas Klauser   // Test const& overload
11117cfc57dSNikolas Klauser   {
11217cfc57dSNikolas Klauser     // Without & qualifier on F's operator()
11317cfc57dSNikolas Klauser     {
11417cfc57dSNikolas Klauser       const std::optional<int> i{0};
11517cfc57dSNikolas Klauser       assert(i.transform(CLVal{}) == 1);
11617cfc57dSNikolas Klauser       ASSERT_SAME_TYPE(decltype(i.transform(CLVal{})), std::optional<int>);
11717cfc57dSNikolas Klauser     }
11817cfc57dSNikolas Klauser 
11917cfc57dSNikolas Klauser     //With & qualifier on F's operator()
12017cfc57dSNikolas Klauser     {
12117cfc57dSNikolas Klauser       const std::optional<int> i{0};
12217cfc57dSNikolas Klauser       const CRefQual l{};
12317cfc57dSNikolas Klauser       assert(i.transform(l) == 1);
12417cfc57dSNikolas Klauser       ASSERT_SAME_TYPE(decltype(i.transform(l)), std::optional<int>);
12517cfc57dSNikolas Klauser     }
12617cfc57dSNikolas Klauser   }
12717cfc57dSNikolas Klauser 
12817cfc57dSNikolas Klauser   // Test && overload
12917cfc57dSNikolas Klauser   {
13017cfc57dSNikolas Klauser     // Without & qualifier on F's operator()
13117cfc57dSNikolas Klauser     {
13217cfc57dSNikolas Klauser       std::optional<int> i{0};
13317cfc57dSNikolas Klauser       assert(std::move(i).transform(RVal{}) == 1);
13417cfc57dSNikolas Klauser       ASSERT_SAME_TYPE(decltype(std::move(i).transform(RVal{})), std::optional<int>);
13517cfc57dSNikolas Klauser     }
13617cfc57dSNikolas Klauser 
13717cfc57dSNikolas Klauser     //With & qualifier on F's operator()
13817cfc57dSNikolas Klauser     {
13917cfc57dSNikolas Klauser       std::optional<int> i{0};
14017cfc57dSNikolas Klauser       assert(i.transform(RVRefQual{}) == 1);
14117cfc57dSNikolas Klauser       ASSERT_SAME_TYPE(decltype(i.transform(RVRefQual{})), std::optional<int>);
14217cfc57dSNikolas Klauser     }
14317cfc57dSNikolas Klauser   }
14417cfc57dSNikolas Klauser 
14517cfc57dSNikolas Klauser   // Test const&& overload
14617cfc57dSNikolas Klauser   {
14717cfc57dSNikolas Klauser     // Without & qualifier on F's operator()
14817cfc57dSNikolas Klauser     {
14917cfc57dSNikolas Klauser       const std::optional<int> i{0};
15017cfc57dSNikolas Klauser       assert(std::move(i).transform(CRVal{}) == 1);
15117cfc57dSNikolas Klauser       ASSERT_SAME_TYPE(decltype(std::move(i).transform(CRVal{})), std::optional<int>);
15217cfc57dSNikolas Klauser     }
15317cfc57dSNikolas Klauser 
15417cfc57dSNikolas Klauser     //With & qualifier on F's operator()
15517cfc57dSNikolas Klauser     {
15617cfc57dSNikolas Klauser       const std::optional<int> i{0};
15717cfc57dSNikolas Klauser       const RVCRefQual l{};
15817cfc57dSNikolas Klauser       assert(i.transform(std::move(l)) == 1);
15917cfc57dSNikolas Klauser       ASSERT_SAME_TYPE(decltype(i.transform(std::move(l))), std::optional<int>);
16017cfc57dSNikolas Klauser     }
16117cfc57dSNikolas Klauser   }
16217cfc57dSNikolas Klauser }
16317cfc57dSNikolas Klauser 
16417cfc57dSNikolas Klauser struct NonConst {
non_constNonConst16517cfc57dSNikolas Klauser   int non_const() { return 1; }
16617cfc57dSNikolas Klauser };
16717cfc57dSNikolas Klauser 
16817cfc57dSNikolas Klauser // check that the lambda body is not instantiated during overload resolution
test_sfinae()16917cfc57dSNikolas Klauser constexpr void test_sfinae() {
17017cfc57dSNikolas Klauser   std::optional<NonConst> opt{};
17117cfc57dSNikolas Klauser   auto l = [](auto&& x) { return x.non_const(); };
17217cfc57dSNikolas Klauser   opt.transform(l);
17317cfc57dSNikolas Klauser   std::move(opt).transform(l);
17417cfc57dSNikolas Klauser }
17517cfc57dSNikolas Klauser 
test()17617cfc57dSNikolas Klauser constexpr bool test() {
17717cfc57dSNikolas Klauser   test_sfinae();
17817cfc57dSNikolas Klauser   test_val_types();
17917cfc57dSNikolas Klauser   std::optional<int> opt;
18017cfc57dSNikolas Klauser   const auto& copt = opt;
18117cfc57dSNikolas Klauser 
18217cfc57dSNikolas Klauser   const auto never_called = [](int) {
18317cfc57dSNikolas Klauser     assert(false);
18417cfc57dSNikolas Klauser     return 0;
18517cfc57dSNikolas Klauser   };
18617cfc57dSNikolas Klauser 
18717cfc57dSNikolas Klauser   opt.transform(never_called);
18817cfc57dSNikolas Klauser   std::move(opt).transform(never_called);
18917cfc57dSNikolas Klauser   copt.transform(never_called);
19017cfc57dSNikolas Klauser   std::move(copt).transform(never_called);
19117cfc57dSNikolas Klauser 
19217cfc57dSNikolas Klauser   std::optional<NoCopy> nc;
19317cfc57dSNikolas Klauser   const auto& cnc = nc;
19417cfc57dSNikolas Klauser   std::move(nc).transform(NoCopy{});
19517cfc57dSNikolas Klauser   std::move(cnc).transform(NoCopy{});
19617cfc57dSNikolas Klauser 
19717cfc57dSNikolas Klauser   std::move(nc).transform(NoMove{});
19817cfc57dSNikolas Klauser   std::move(cnc).transform(NoMove{});
19917cfc57dSNikolas Klauser 
20017cfc57dSNikolas Klauser   return true;
20117cfc57dSNikolas Klauser }
20217cfc57dSNikolas Klauser 
main(int,char **)20317cfc57dSNikolas Klauser int main(int, char**) {
20417cfc57dSNikolas Klauser   test();
20517cfc57dSNikolas Klauser   static_assert(test());
206c31cf74cSLouis Dionne   return 0;
20717cfc57dSNikolas Klauser }
208