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