//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 // // template constexpr optional or_else(F&&) &&; // template constexpr optional or_else(F&&) const&; #include "MoveOnly.h" #include #include struct NonMovable { NonMovable() = default; NonMovable(NonMovable&&) = delete; }; template concept has_or_else = requires(Opt&& opt, F&& f) { {std::forward(opt).or_else(std::forward(f))}; }; template std::optional return_optional() {} static_assert(has_or_else&, decltype(return_optional)>); static_assert(has_or_else&&, decltype(return_optional)>); static_assert(!has_or_else&, decltype(return_optional)>); static_assert(has_or_else&&, decltype(return_optional)>); static_assert(!has_or_else&, decltype(return_optional)>); static_assert(!has_or_else&&, decltype(return_optional)>); std::optional take_int(int) { return 0; } void take_int_return_void(int) {} static_assert(!has_or_else, decltype(take_int)>); static_assert(!has_or_else, decltype(take_int_return_void)>); static_assert(!has_or_else, int>); constexpr bool test() { { std::optional opt; assert(opt.or_else([] { return std::optional{0}; }) == 0); opt = 1; (void)opt.or_else([] { assert(false); return std::optional{}; }); } { std::optional opt; opt = std::move(opt).or_else([] { return std::optional{MoveOnly{}}; }); (void)std::move(opt).or_else([] { assert(false); return std::optional{}; }); } #if TEST_STD_VER >= 26 { int i = 2; std::optional opt; assert(opt.or_else([&] { return std::optional{i}; }) == i); int j = 3; opt = j; (void)opt.or_else([] { assert(false); return std::optional{}; }); assert(opt == j); } { int i = 2; const std::optional opt; assert(opt.or_else([&] { return std::optional{i}; }) == i); } { int i = 2; std::optional opt; assert(std::move(opt).or_else([&] { return std::optional{i}; }) == i); int j = 3; opt = j; (void)std::move(opt).or_else([] { assert(false); return std::optional{}; }); assert(opt == j); } { int i = 2; const std::optional opt = i; assert(std::move(opt).or_else([] { assert(false); return std::optional{}; }) == i); } #endif return true; } int main(int, char**) { test(); static_assert(test()); return 0; }