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