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 and_then(F&&) &; 17 // template<class F> constexpr auto and_then(F&&) &&; 18 // template<class F> constexpr auto and_then(F&&) const&; 19 // template<class F> constexpr auto and_then(F&&) const&&; 20 21 #include <cassert> 22 #include <optional> 23 24 #include "test_macros.h" 25 26 struct LVal { 27 constexpr std::optional<int> operator()(int&) { return 1; } 28 std::optional<int> operator()(const int&) = delete; 29 std::optional<int> operator()(int&&) = delete; 30 std::optional<int> operator()(const int&&) = delete; 31 }; 32 33 struct CLVal { 34 std::optional<int> operator()(int&) = delete; 35 constexpr std::optional<int> operator()(const int&) { return 1; } 36 std::optional<int> operator()(int&&) = delete; 37 std::optional<int> operator()(const int&&) = delete; 38 }; 39 40 struct RVal { 41 std::optional<int> operator()(int&) = delete; 42 std::optional<int> operator()(const int&) = delete; 43 constexpr std::optional<int> operator()(int&&) { return 1; } 44 std::optional<int> operator()(const int&&) = delete; 45 }; 46 47 struct CRVal { 48 std::optional<int> operator()(int&) = delete; 49 std::optional<int> operator()(const int&) = delete; 50 std::optional<int> operator()(int&&) = delete; 51 constexpr std::optional<int> operator()(const int&&) { return 1; } 52 }; 53 54 struct RefQual { 55 constexpr std::optional<int> operator()(int) & { return 1; } 56 std::optional<int> operator()(int) const& = delete; 57 std::optional<int> operator()(int) && = delete; 58 std::optional<int> operator()(int) const&& = delete; 59 }; 60 61 struct CRefQual { 62 std::optional<int> operator()(int) & = delete; 63 constexpr std::optional<int> operator()(int) const& { return 1; } 64 std::optional<int> operator()(int) && = delete; 65 std::optional<int> operator()(int) const&& = delete; 66 }; 67 68 struct RVRefQual { 69 std::optional<int> operator()(int) & = delete; 70 std::optional<int> operator()(int) const& = delete; 71 constexpr std::optional<int> operator()(int) && { return 1; } 72 std::optional<int> operator()(int) const&& = delete; 73 }; 74 75 struct RVCRefQual { 76 std::optional<int> operator()(int) & = delete; 77 std::optional<int> operator()(int) const& = delete; 78 std::optional<int> operator()(int) && = delete; 79 constexpr std::optional<int> operator()(int) const&& { return 1; } 80 }; 81 82 struct NOLVal { 83 constexpr std::optional<int> operator()(int&) { return std::nullopt; } 84 std::optional<int> operator()(const int&) = delete; 85 std::optional<int> operator()(int&&) = delete; 86 std::optional<int> operator()(const int&&) = delete; 87 }; 88 89 struct NOCLVal { 90 std::optional<int> operator()(int&) = delete; 91 constexpr std::optional<int> operator()(const int&) { return std::nullopt; } 92 std::optional<int> operator()(int&&) = delete; 93 std::optional<int> operator()(const int&&) = delete; 94 }; 95 96 struct NORVal { 97 std::optional<int> operator()(int&) = delete; 98 std::optional<int> operator()(const int&) = delete; 99 constexpr std::optional<int> operator()(int&&) { return std::nullopt; } 100 std::optional<int> operator()(const int&&) = delete; 101 }; 102 103 struct NOCRVal { 104 std::optional<int> operator()(int&) = delete; 105 std::optional<int> operator()(const int&) = delete; 106 std::optional<int> operator()(int&&) = delete; 107 constexpr std::optional<int> operator()(const int&&) { return std::nullopt; } 108 }; 109 110 struct NORefQual { 111 constexpr std::optional<int> operator()(int) & { return std::nullopt; } 112 std::optional<int> operator()(int) const& = delete; 113 std::optional<int> operator()(int) && = delete; 114 std::optional<int> operator()(int) const&& = delete; 115 }; 116 117 struct NOCRefQual { 118 std::optional<int> operator()(int) & = delete; 119 constexpr std::optional<int> operator()(int) const& { return std::nullopt; } 120 std::optional<int> operator()(int) && = delete; 121 std::optional<int> operator()(int) const&& = delete; 122 }; 123 124 struct NORVRefQual { 125 std::optional<int> operator()(int) & = delete; 126 std::optional<int> operator()(int) const& = delete; 127 constexpr std::optional<int> operator()(int) && { return std::nullopt; } 128 std::optional<int> operator()(int) const&& = delete; 129 }; 130 131 struct NORVCRefQual { 132 std::optional<int> operator()(int) & = delete; 133 std::optional<int> operator()(int) const& = delete; 134 std::optional<int> operator()(int) && = delete; 135 constexpr std::optional<int> operator()(int) const&& { return std::nullopt; } 136 }; 137 138 struct NoCopy { 139 NoCopy() = default; 140 NoCopy(const NoCopy&) { assert(false); } 141 std::optional<int> operator()(const NoCopy&&) { return 1; } 142 }; 143 144 struct NonConst { 145 std::optional<int> non_const() { return 1; } 146 }; 147 148 constexpr void test_val_types() { 149 // Test & overload 150 { 151 // Without & qualifier on F's operator() 152 { 153 std::optional<int> i{0}; 154 assert(i.and_then(LVal{}) == 1); 155 assert(i.and_then(NOLVal{}) == std::nullopt); 156 ASSERT_SAME_TYPE(decltype(i.and_then(LVal{})), std::optional<int>); 157 } 158 159 //With & qualifier on F's operator() 160 { 161 std::optional<int> i{0}; 162 RefQual l{}; 163 assert(i.and_then(l) == 1); 164 NORefQual nl{}; 165 assert(i.and_then(nl) == std::nullopt); 166 ASSERT_SAME_TYPE(decltype(i.and_then(l)), std::optional<int>); 167 } 168 } 169 170 // Test const& overload 171 { 172 // Without & qualifier on F's operator() 173 { 174 const std::optional<int> i{0}; 175 assert(i.and_then(CLVal{}) == 1); 176 assert(i.and_then(NOCLVal{}) == std::nullopt); 177 ASSERT_SAME_TYPE(decltype(i.and_then(CLVal{})), std::optional<int>); 178 } 179 180 //With & qualifier on F's operator() 181 { 182 const std::optional<int> i{0}; 183 const CRefQual l{}; 184 assert(i.and_then(l) == 1); 185 const NOCRefQual nl{}; 186 assert(i.and_then(nl) == std::nullopt); 187 ASSERT_SAME_TYPE(decltype(i.and_then(l)), std::optional<int>); 188 } 189 } 190 191 // Test && overload 192 { 193 // Without & qualifier on F's operator() 194 { 195 std::optional<int> i{0}; 196 assert(std::move(i).and_then(RVal{}) == 1); 197 assert(std::move(i).and_then(NORVal{}) == std::nullopt); 198 ASSERT_SAME_TYPE(decltype(std::move(i).and_then(RVal{})), std::optional<int>); 199 } 200 201 //With & qualifier on F's operator() 202 { 203 std::optional<int> i{0}; 204 assert(i.and_then(RVRefQual{}) == 1); 205 assert(i.and_then(NORVRefQual{}) == std::nullopt); 206 ASSERT_SAME_TYPE(decltype(i.and_then(RVRefQual{})), std::optional<int>); 207 } 208 } 209 210 // Test const&& overload 211 { 212 // Without & qualifier on F's operator() 213 { 214 const std::optional<int> i{0}; 215 assert(std::move(i).and_then(CRVal{}) == 1); 216 assert(std::move(i).and_then(NOCRVal{}) == std::nullopt); 217 ASSERT_SAME_TYPE(decltype(std::move(i).and_then(CRVal{})), std::optional<int>); 218 } 219 220 //With & qualifier on F's operator() 221 { 222 const std::optional<int> i{0}; 223 const RVCRefQual l{}; 224 assert(i.and_then(std::move(l)) == 1); 225 const NORVCRefQual nl{}; 226 assert(i.and_then(std::move(nl)) == std::nullopt); 227 ASSERT_SAME_TYPE(decltype(i.and_then(std::move(l))), std::optional<int>); 228 } 229 } 230 } 231 232 // check that the lambda body is not instantiated during overload resolution 233 constexpr void test_sfinae() { 234 std::optional<NonConst> opt{}; 235 auto l = [](auto&& x) { return x.non_const(); }; 236 opt.and_then(l); 237 std::move(opt).and_then(l); 238 } 239 240 constexpr bool test() { 241 test_val_types(); 242 std::optional<int> opt{}; 243 const auto& copt = opt; 244 245 const auto never_called = [](int) { 246 assert(false); 247 return std::optional<int>{}; 248 }; 249 250 opt.and_then(never_called); 251 std::move(opt).and_then(never_called); 252 copt.and_then(never_called); 253 std::move(copt).and_then(never_called); 254 255 std::optional<NoCopy> nc; 256 const auto& cnc = nc; 257 std::move(cnc).and_then(NoCopy{}); 258 std::move(nc).and_then(NoCopy{}); 259 260 return true; 261 } 262 263 int main(int, char**) { 264 test(); 265 static_assert(test()); 266 return 0; 267 } 268