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