352 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++03, c++11, c++14, c++17, c++2010 11// <optional>12 13// template<class F> constexpr auto and_then(F&&) &;14// template<class F> constexpr auto and_then(F&&) &&;15// template<class F> constexpr auto and_then(F&&) const&;16// template<class F> constexpr auto and_then(F&&) const&&;17 18#include <cassert>19#include <concepts>20#include <optional>21 22#include "test_macros.h"23 24struct LVal {25 constexpr std::optional<int> operator()(int&) { return 1; }26 std::optional<int> operator()(const int&) = delete;27 std::optional<int> operator()(int&&) = delete;28 std::optional<int> operator()(const int&&) = delete;29};30 31struct CLVal {32 std::optional<int> operator()(int&) = delete;33 constexpr std::optional<int> operator()(const int&) { return 1; }34 std::optional<int> operator()(int&&) = delete;35 std::optional<int> operator()(const int&&) = delete;36};37 38struct RVal {39 std::optional<int> operator()(int&) = delete;40 std::optional<int> operator()(const int&) = delete;41 constexpr std::optional<int> operator()(int&&) { return 1; }42 std::optional<int> operator()(const int&&) = delete;43};44 45struct CRVal {46 std::optional<int> operator()(int&) = delete;47 std::optional<int> operator()(const int&) = delete;48 std::optional<int> operator()(int&&) = delete;49 constexpr std::optional<int> operator()(const int&&) { return 1; }50};51 52struct RefQual {53 constexpr std::optional<int> operator()(int) & { return 1; }54 std::optional<int> operator()(int) const& = delete;55 std::optional<int> operator()(int) && = delete;56 std::optional<int> operator()(int) const&& = delete;57};58 59struct CRefQual {60 std::optional<int> operator()(int) & = delete;61 constexpr std::optional<int> operator()(int) const& { return 1; }62 std::optional<int> operator()(int) && = delete;63 std::optional<int> operator()(int) const&& = delete;64};65 66struct RVRefQual {67 std::optional<int> operator()(int) & = delete;68 std::optional<int> operator()(int) const& = delete;69 constexpr std::optional<int> operator()(int) && { return 1; }70 std::optional<int> operator()(int) const&& = delete;71};72 73struct RVCRefQual {74 std::optional<int> operator()(int) & = delete;75 std::optional<int> operator()(int) const& = delete;76 std::optional<int> operator()(int) && = delete;77 constexpr std::optional<int> operator()(int) const&& { return 1; }78};79 80struct NOLVal {81 constexpr std::optional<int> operator()(int&) { return std::nullopt; }82 std::optional<int> operator()(const int&) = delete;83 std::optional<int> operator()(int&&) = delete;84 std::optional<int> operator()(const int&&) = delete;85};86 87struct NOCLVal {88 std::optional<int> operator()(int&) = delete;89 constexpr std::optional<int> operator()(const int&) { return std::nullopt; }90 std::optional<int> operator()(int&&) = delete;91 std::optional<int> operator()(const int&&) = delete;92};93 94struct NORVal {95 std::optional<int> operator()(int&) = delete;96 std::optional<int> operator()(const int&) = delete;97 constexpr std::optional<int> operator()(int&&) { return std::nullopt; }98 std::optional<int> operator()(const int&&) = delete;99};100 101struct NOCRVal {102 std::optional<int> operator()(int&) = delete;103 std::optional<int> operator()(const int&) = delete;104 std::optional<int> operator()(int&&) = delete;105 constexpr std::optional<int> operator()(const int&&) { return std::nullopt; }106};107 108struct NORefQual {109 constexpr std::optional<int> operator()(int) & { return std::nullopt; }110 std::optional<int> operator()(int) const& = delete;111 std::optional<int> operator()(int) && = delete;112 std::optional<int> operator()(int) const&& = delete;113};114 115struct NOCRefQual {116 std::optional<int> operator()(int) & = delete;117 constexpr std::optional<int> operator()(int) const& { return std::nullopt; }118 std::optional<int> operator()(int) && = delete;119 std::optional<int> operator()(int) const&& = delete;120};121 122struct NORVRefQual {123 std::optional<int> operator()(int) & = delete;124 std::optional<int> operator()(int) const& = delete;125 constexpr std::optional<int> operator()(int) && { return std::nullopt; }126 std::optional<int> operator()(int) const&& = delete;127};128 129struct NORVCRefQual {130 std::optional<int> operator()(int) & = delete;131 std::optional<int> operator()(int) const& = delete;132 std::optional<int> operator()(int) && = delete;133 constexpr std::optional<int> operator()(int) const&& { return std::nullopt; }134};135 136struct NoCopy {137 NoCopy() = default;138 NoCopy(const NoCopy&) { assert(false); }139 std::optional<int> operator()(const NoCopy&&) { return 1; }140};141 142struct NonConst {143 std::optional<int> non_const() { return 1; }144};145 146constexpr void test_val_types() {147 // Test & overload148 {149 // Without & qualifier on F's operator()150 {151 std::optional<int> i{0};152 assert(i.and_then(LVal{}) == 1);153 assert(i.and_then(NOLVal{}) == std::nullopt);154 ASSERT_SAME_TYPE(decltype(i.and_then(LVal{})), std::optional<int>);155 }156 157 //With & qualifier on F's operator()158 {159 std::optional<int> i{0};160 RefQual l{};161 assert(i.and_then(l) == 1);162 NORefQual nl{};163 assert(i.and_then(nl) == std::nullopt);164 ASSERT_SAME_TYPE(decltype(i.and_then(l)), std::optional<int>);165 }166 }167 168 // Test const& overload169 {170 // Without & qualifier on F's operator()171 {172 const std::optional<int> i{0};173 assert(i.and_then(CLVal{}) == 1);174 assert(i.and_then(NOCLVal{}) == std::nullopt);175 ASSERT_SAME_TYPE(decltype(i.and_then(CLVal{})), std::optional<int>);176 }177 178 //With & qualifier on F's operator()179 {180 const std::optional<int> i{0};181 const CRefQual l{};182 assert(i.and_then(l) == 1);183 const NOCRefQual nl{};184 assert(i.and_then(nl) == std::nullopt);185 ASSERT_SAME_TYPE(decltype(i.and_then(l)), std::optional<int>);186 }187 }188 189 // Test && overload190 {191 // Without & qualifier on F's operator()192 {193 std::optional<int> i{0};194 assert(std::move(i).and_then(RVal{}) == 1);195 assert(std::move(i).and_then(NORVal{}) == std::nullopt);196 ASSERT_SAME_TYPE(decltype(std::move(i).and_then(RVal{})), std::optional<int>);197 }198 199 //With & qualifier on F's operator()200 {201 std::optional<int> i{0};202 assert(i.and_then(RVRefQual{}) == 1);203 assert(i.and_then(NORVRefQual{}) == std::nullopt);204 ASSERT_SAME_TYPE(decltype(i.and_then(RVRefQual{})), std::optional<int>);205 }206 }207 208 // Test const&& overload209 {210 // Without & qualifier on F's operator()211 {212 const std::optional<int> i{0};213 assert(std::move(i).and_then(CRVal{}) == 1);214 assert(std::move(i).and_then(NOCRVal{}) == std::nullopt);215 ASSERT_SAME_TYPE(decltype(std::move(i).and_then(CRVal{})), std::optional<int>);216 }217 218 //With & qualifier on F's operator()219 {220 const std::optional<int> i{0};221 const RVCRefQual l{};222 assert(i.and_then(std::move(l)) == 1);223 const NORVCRefQual nl{};224 assert(i.and_then(std::move(nl)) == std::nullopt);225 ASSERT_SAME_TYPE(decltype(i.and_then(std::move(l))), std::optional<int>);226 }227 }228}229 230// check that the lambda body is not instantiated during overload resolution231constexpr void test_sfinae() {232 std::optional<NonConst> opt{};233 auto l = [](auto&& x) { return x.non_const(); };234 opt.and_then(l);235 std::move(opt).and_then(l);236}237 238constexpr bool test() {239 test_val_types();240 std::optional<int> opt{};241 const auto& copt = opt;242 243 const auto never_called = [](int) {244 assert(false);245 return std::optional<int>{};246 };247 248 opt.and_then(never_called);249 std::move(opt).and_then(never_called);250 copt.and_then(never_called);251 std::move(copt).and_then(never_called);252 253 std::optional<NoCopy> nc;254 const auto& cnc = nc;255 std::move(cnc).and_then(NoCopy{});256 std::move(nc).and_then(NoCopy{});257 258 return true;259}260 261#if TEST_STD_VER >= 26262constexpr bool test_ref() {263 // Test & overload264 {265 // Without & qualifier on F's operator()266 {267 int j = 42;268 std::optional<int&> i{j};269 std::same_as<std::optional<int>> decltype(auto) r = i.and_then(LVal{});270 271 assert(r == 1);272 assert(i.and_then(NOLVal{}) == std::nullopt);273 }274 275 //With & qualifier on F's operator()276 {277 int j = 42;278 std::optional<int&> i{j};279 RefQual l{};280 NORefQual nl{};281 std::same_as<std::optional<int>> decltype(auto) r = i.and_then(l);282 283 assert(r == 1);284 assert(i.and_then(nl) == std::nullopt);285 }286 }287 288 // Test const& overload289 {290 // Without & qualifier on F's operator()291 {292 int j = 42;293 std::optional<const int&> i{j};294 std::same_as<std::optional<int>> decltype(auto) r = i.and_then(CLVal{});295 296 assert(r == 1);297 assert(i.and_then(NOCLVal{}) == std::nullopt);298 }299 300 //With & qualifier on F's operator()301 {302 int j = 42;303 const std::optional<int&> i{j};304 const CRefQual l{};305 const NOCRefQual nl{};306 std::same_as<std::optional<int>> decltype(auto) r = i.and_then(l);307 308 assert(r == 1);309 assert(i.and_then(nl) == std::nullopt);310 }311 }312 // Test && overload313 {314 //With & qualifier on F's operator()315 {316 int j = 42;317 std::optional<int&> i{j};318 std::same_as<std::optional<int>> decltype(auto) r = i.and_then(RVRefQual{});319 320 assert(r == 1);321 assert(i.and_then(NORVRefQual{}) == std::nullopt);322 }323 }324 325 // Test const&& overload326 {327 //With & qualifier on F's operator()328 {329 int j = 42;330 const std::optional<int&> i{j};331 const RVCRefQual l{};332 const NORVCRefQual nl{};333 std::same_as<std::optional<int>> decltype(auto) r = i.and_then(std::move(l));334 335 assert(r == 1);336 assert(i.and_then(std::move(nl)) == std::nullopt);337 }338 }339 return true;340}341#endif342 343int main(int, char**) {344 test();345 static_assert(test());346#if TEST_STD_VER >= 26347 test_ref();348 static_assert(test_ref());349#endif350 return 0;351}352