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 // GCC has a issue for `Guaranteed copy elision for potentially-overlapping non-static data members`, 12 // please refer to: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108333 13 // XFAIL: gcc-14 14 15 // <expected> 16 17 // template<class F> constexpr auto transform(F&& f) &; 18 // template<class F> constexpr auto transform(F&& f) const &; 19 // template<class F> constexpr auto transform(F&& f) &&; 20 // template<class F> constexpr auto transform(F&& f) const &&; 21 22 #include <expected> 23 #include <concepts> 24 #include <cassert> 25 #include <memory> 26 #include <type_traits> 27 #include <utility> 28 29 #include "../../types.h" 30 31 struct LVal { 32 constexpr int operator()(int&) { return 1; } 33 int operator()(const int&) = delete; 34 int operator()(int&&) = delete; 35 int operator()(const int&&) = delete; 36 }; 37 38 struct CLVal { 39 int operator()(int&) = delete; 40 constexpr int operator()(const int&) { return 1; } 41 int operator()(int&&) = delete; 42 int operator()(const int&&) = delete; 43 }; 44 45 struct RVal { 46 int operator()(int&) = delete; 47 int operator()(const int&) = delete; 48 constexpr int operator()(int&&) { return 1; } 49 int operator()(const int&&) = delete; 50 }; 51 52 struct CRVal { 53 int operator()(int&) = delete; 54 int operator()(const int&) = delete; 55 int operator()(int&&) = delete; 56 constexpr int operator()(const int&&) { return 1; } 57 }; 58 59 struct RefQual { 60 constexpr int operator()(int) & { return 1; } 61 int operator()(int) const& = delete; 62 int operator()(int) && = delete; 63 int operator()(int) const&& = delete; 64 }; 65 66 struct CRefQual { 67 int operator()(int) & = delete; 68 constexpr int operator()(int) const& { return 1; } 69 int operator()(int) && = delete; 70 int operator()(int) const&& = delete; 71 }; 72 73 struct RVRefQual { 74 int operator()(int) & = delete; 75 int operator()(int) const& = delete; 76 constexpr int operator()(int) && { return 1; } 77 int operator()(int) const&& = delete; 78 }; 79 80 struct RVCRefQual { 81 int operator()(int) & = delete; 82 int operator()(int) const& = delete; 83 int operator()(int) && = delete; 84 constexpr int operator()(int) const&& { return 1; } 85 }; 86 87 struct NonCopy { 88 int value; 89 constexpr explicit NonCopy(int val) : value(val) {} 90 NonCopy(const NonCopy&) = delete; 91 }; 92 93 struct NonConst { 94 int non_const() { return 1; } 95 }; 96 97 template <class E, class F> 98 concept has_transform = 99 requires(E&& e, F&& f) { 100 { std::forward<E>(e).transform(std::forward<F>(f)) }; 101 }; 102 103 // clang-format off 104 // [LWG 3877] https://cplusplus.github.io/LWG/issue3877, check constraint failing but not compile error inside the function body. 105 static_assert(!has_transform<const std::expected<int, std::unique_ptr<int>>&, int()>); 106 static_assert(!has_transform<const std::expected<int, std::unique_ptr<int>>&&, int()>); 107 108 // [LWG 3983] https://cplusplus.github.io/LWG/issue3938, check std::expected monadic ops well-formed with move-only error_type. 109 // There are no effects for `&` and `const &` overload, because the constraints requires is_constructible_v<E, decltype(error())> is true. 110 static_assert(has_transform<std::expected<int, MoveOnlyErrorType>&&, int(int)>); 111 static_assert(has_transform<const std::expected<int, MoveOnlyErrorType>&&, int(const int)>); 112 113 constexpr void test_val_types() { 114 // Test & overload 115 { 116 // Without & qualifier on F's operator() 117 { 118 std::expected<int, int> e(0); 119 std::same_as<std::expected<int, int>> decltype(auto) val = e.transform(LVal{}); 120 assert(val == 1); 121 } 122 123 // With & qualifier on F's operator() 124 { 125 std::expected<int, int> e(0); 126 RefQual l{}; 127 std::same_as<std::expected<int, int>> decltype(auto) val = e.transform(l); 128 assert(val == 1); 129 } 130 } 131 132 // Test const& overload 133 { 134 // Without & qualifier on F's operator() 135 { 136 const std::expected<int, int> e(0); 137 std::same_as<std::expected<int, int>> decltype(auto) val = e.transform(CLVal{}); 138 assert(val == 1); 139 } 140 141 // With & qualifier on F's operator() 142 { 143 const std::expected<int, int> e(0); 144 const CRefQual l{}; 145 std::same_as<std::expected<int, int>> decltype(auto) val = e.transform(l); 146 assert(val == 1); 147 } 148 } 149 150 // Test && overload 151 { 152 // Without & qualifier on F's operator() 153 { 154 std::expected<int, int> e(0); 155 std::same_as<std::expected<int, int>> decltype(auto) val = std::move(e).transform(RVal{}); 156 assert(val == 1); 157 } 158 159 // With & qualifier on F's operator() 160 { 161 std::expected<int, int> e(0); 162 std::same_as<std::expected<int, int>> decltype(auto) val = std::move(e).transform(RVRefQual{}); 163 assert(val == 1); 164 } 165 } 166 167 // Test const&& overload 168 { 169 // Without & qualifier on F's operator() 170 { 171 const std::expected<int, int> e(0); 172 std::same_as<std::expected<int, int>> decltype(auto) val = std::move(e).transform(CRVal{}); 173 assert(val == 1); 174 } 175 176 // With & qualifier on F's operator() 177 { 178 const std::expected<int, int> e(0); 179 const RVCRefQual l{}; 180 std::same_as<std::expected<int, int>> decltype(auto) val = e.transform(std::move(l)); 181 assert(val == 1); 182 } 183 } 184 } 185 // clang-format on 186 187 constexpr void test_take_val_return_void() { 188 std::expected<int, int> e(1); 189 int val = 0; 190 (void)e.transform([&val]<typename T>(T&&) -> void { 191 static_assert(std::is_same_v<T, int&>); 192 assert(val == 0); 193 val = 1; 194 }); 195 assert(val == 1); 196 (void)std::move(e).transform([&val]<typename T>(T&&) -> void { 197 static_assert(std::is_same_v<T, int>); 198 assert(val == 1); 199 val = 2; 200 }); 201 202 const auto& ce = e; 203 assert(val == 2); 204 (void)ce.transform([&val]<typename T>(T&&) -> void { 205 static_assert(std::is_same_v<T, const int&>); 206 assert(val == 2); 207 val = 3; 208 }); 209 assert(val == 3); 210 (void)std::move(ce).transform([&val]<typename T>(T&&) -> void { 211 static_assert(std::is_same_v<T, const int>); 212 assert(val == 3); 213 val = 4; 214 }); 215 assert(val == 4); 216 } 217 218 // check val member is direct-non-list-initialized with invoke(std::forward<F>(f), value()) 219 constexpr void test_direct_non_list_init() { 220 auto xform = [](int i) { return NonCopy(i); }; 221 std::expected<int, int> e(2); 222 std::expected<NonCopy, int> n = e.transform(xform); 223 assert(n.value().value == 2); 224 } 225 226 // check that the lambda body is not instantiated during overload resolution 227 constexpr void test_sfinae() { 228 std::expected<NonConst, int> e(std::unexpected<int>(2)); 229 auto l = [](auto&& x) { return x.non_const(); }; 230 (void)e.transform(l); 231 (void)std::move(e).transform(l); 232 233 std::expected<int, int> e1(std::unexpected<int>(1)); 234 const auto& ce1 = e1; 235 const auto never_called = [](int) { 236 assert(false); 237 return std::expected<int, int>(); 238 }; 239 240 (void)e1.transform(never_called); 241 (void)std::move(e1).transform(never_called); 242 (void)ce1.transform(never_called); 243 (void)std::move(ce1).transform(never_called); 244 } 245 246 constexpr void test_move_only_error_type() { 247 // Test && 248 { 249 std::expected<int, MoveOnlyErrorType> e; 250 auto l = [](int) { return 0; }; 251 (void)std::move(e).transform(l); 252 } 253 254 // Test const&& 255 { 256 const std::expected<int, MoveOnlyErrorType> e; 257 auto l = [](const int) { return 0; }; 258 (void)std::move(e).transform(l); 259 } 260 } 261 262 constexpr bool test() { 263 test_sfinae(); 264 test_val_types(); 265 test_direct_non_list_init(); 266 test_move_only_error_type(); 267 return true; 268 } 269 270 int main(int, char**) { 271 test(); 272 static_assert(test()); 273 274 return 0; 275 } 276