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