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 // XFAIL: availability-bad_optional_access-missing && !no-exceptions 12 13 // <optional> 14 15 // template<class F> constexpr auto transform(F&&) &; 16 // template<class F> constexpr auto transform(F&&) &&; 17 // template<class F> constexpr auto transform(F&&) const&; 18 // template<class F> constexpr auto transform(F&&) const&&; 19 20 #include "test_macros.h" 21 #include <cassert> 22 #include <optional> 23 #include <type_traits> 24 25 struct LVal { 26 constexpr int operator()(int&) { return 1; } 27 int operator()(const int&) = delete; 28 int operator()(int&&) = delete; 29 int operator()(const int&&) = delete; 30 }; 31 32 struct CLVal { 33 int operator()(int&) = delete; 34 constexpr int operator()(const int&) { return 1; } 35 int operator()(int&&) = delete; 36 int operator()(const int&&) = delete; 37 }; 38 39 struct RVal { 40 int operator()(int&) = delete; 41 int operator()(const int&) = delete; 42 constexpr int operator()(int&&) { return 1; } 43 int operator()(const int&&) = delete; 44 }; 45 46 struct CRVal { 47 int operator()(int&) = delete; 48 int operator()(const int&) = delete; 49 int operator()(int&&) = delete; 50 constexpr int operator()(const int&&) { return 1; } 51 }; 52 53 struct RefQual { 54 constexpr int operator()(int) & { return 1; } 55 int operator()(int) const& = delete; 56 int operator()(int) && = delete; 57 int operator()(int) const&& = delete; 58 }; 59 60 struct CRefQual { 61 int operator()(int) & = delete; 62 constexpr int operator()(int) const& { return 1; } 63 int operator()(int) && = delete; 64 int operator()(int) const&& = delete; 65 }; 66 67 struct RVRefQual { 68 int operator()(int) & = delete; 69 int operator()(int) const& = delete; 70 constexpr int operator()(int) && { return 1; } 71 int operator()(int) const&& = delete; 72 }; 73 74 struct RVCRefQual { 75 int operator()(int) & = delete; 76 int operator()(int) const& = delete; 77 int operator()(int) && = delete; 78 constexpr int operator()(int) const&& { return 1; } 79 }; 80 81 struct NoCopy { 82 NoCopy() = default; 83 NoCopy(const NoCopy&) { assert(false); } 84 int operator()(const NoCopy&&) { return 1; } 85 }; 86 87 struct NoMove { 88 NoMove() = default; 89 NoMove(NoMove&&) = delete; 90 NoMove operator()(const NoCopy&&) { return NoMove{}; } 91 }; 92 93 constexpr void test_val_types() { 94 // Test & overload 95 { 96 // Without & qualifier on F's operator() 97 { 98 std::optional<int> i{0}; 99 assert(i.transform(LVal{}) == 1); 100 ASSERT_SAME_TYPE(decltype(i.transform(LVal{})), std::optional<int>); 101 } 102 103 //With & qualifier on F's operator() 104 { 105 std::optional<int> i{0}; 106 RefQual l{}; 107 assert(i.transform(l) == 1); 108 ASSERT_SAME_TYPE(decltype(i.transform(l)), std::optional<int>); 109 } 110 } 111 112 // Test const& overload 113 { 114 // Without & qualifier on F's operator() 115 { 116 const std::optional<int> i{0}; 117 assert(i.transform(CLVal{}) == 1); 118 ASSERT_SAME_TYPE(decltype(i.transform(CLVal{})), std::optional<int>); 119 } 120 121 //With & qualifier on F's operator() 122 { 123 const std::optional<int> i{0}; 124 const CRefQual l{}; 125 assert(i.transform(l) == 1); 126 ASSERT_SAME_TYPE(decltype(i.transform(l)), std::optional<int>); 127 } 128 } 129 130 // Test && overload 131 { 132 // Without & qualifier on F's operator() 133 { 134 std::optional<int> i{0}; 135 assert(std::move(i).transform(RVal{}) == 1); 136 ASSERT_SAME_TYPE(decltype(std::move(i).transform(RVal{})), std::optional<int>); 137 } 138 139 //With & qualifier on F's operator() 140 { 141 std::optional<int> i{0}; 142 assert(i.transform(RVRefQual{}) == 1); 143 ASSERT_SAME_TYPE(decltype(i.transform(RVRefQual{})), std::optional<int>); 144 } 145 } 146 147 // Test const&& overload 148 { 149 // Without & qualifier on F's operator() 150 { 151 const std::optional<int> i{0}; 152 assert(std::move(i).transform(CRVal{}) == 1); 153 ASSERT_SAME_TYPE(decltype(std::move(i).transform(CRVal{})), std::optional<int>); 154 } 155 156 //With & qualifier on F's operator() 157 { 158 const std::optional<int> i{0}; 159 const RVCRefQual l{}; 160 assert(i.transform(std::move(l)) == 1); 161 ASSERT_SAME_TYPE(decltype(i.transform(std::move(l))), std::optional<int>); 162 } 163 } 164 } 165 166 struct NonConst { 167 int non_const() { return 1; } 168 }; 169 170 // check that the lambda body is not instantiated during overload resolution 171 constexpr void test_sfinae() { 172 std::optional<NonConst> opt{}; 173 auto l = [](auto&& x) { return x.non_const(); }; 174 opt.transform(l); 175 std::move(opt).transform(l); 176 } 177 178 constexpr bool test() { 179 test_sfinae(); 180 test_val_types(); 181 std::optional<int> opt; 182 const auto& copt = opt; 183 184 const auto never_called = [](int) { 185 assert(false); 186 return 0; 187 }; 188 189 opt.transform(never_called); 190 std::move(opt).transform(never_called); 191 copt.transform(never_called); 192 std::move(copt).transform(never_called); 193 194 std::optional<NoCopy> nc; 195 const auto& cnc = nc; 196 std::move(nc).transform(NoCopy{}); 197 std::move(cnc).transform(NoCopy{}); 198 199 std::move(nc).transform(NoMove{}); 200 std::move(cnc).transform(NoMove{}); 201 202 return true; 203 } 204 205 int main(int, char**) { 206 test(); 207 static_assert(test()); 208 return 0; 209 } 210