100 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// <optional>11 12// template<class F> constexpr optional or_else(F&&) &&;13// template<class F> constexpr optional or_else(F&&) const&;14 15#include "MoveOnly.h"16 17#include <cassert>18#include <optional>19 20struct NonMovable {21 NonMovable() = default;22 NonMovable(NonMovable&&) = delete;23};24 25template <class Opt, class F>26concept has_or_else = requires(Opt&& opt, F&& f) {27 {std::forward<Opt>(opt).or_else(std::forward<F>(f))};28};29 30template <class T>31std::optional<T> return_optional() {}32 33static_assert(has_or_else<std::optional<int>&, decltype(return_optional<int>)>);34static_assert(has_or_else<std::optional<int>&&, decltype(return_optional<int>)>);35static_assert(!has_or_else<std::optional<MoveOnly>&, decltype(return_optional<MoveOnly>)>);36static_assert(has_or_else<std::optional<MoveOnly>&&, decltype(return_optional<MoveOnly>)>);37static_assert(!has_or_else<std::optional<NonMovable>&, decltype(return_optional<NonMovable>)>);38static_assert(!has_or_else<std::optional<NonMovable>&&, decltype(return_optional<NonMovable>)>);39 40std::optional<int> take_int(int) { return 0; }41void take_int_return_void(int) {}42 43static_assert(!has_or_else<std::optional<int>, decltype(take_int)>);44static_assert(!has_or_else<std::optional<int>, decltype(take_int_return_void)>);45static_assert(!has_or_else<std::optional<int>, int>);46 47constexpr bool test() {48 {49 std::optional<int> opt;50 assert(opt.or_else([] { return std::optional<int>{0}; }) == 0);51 opt = 1;52 opt.or_else([] {53 assert(false);54 return std::optional<int>{};55 });56 }57 {58 std::optional<MoveOnly> opt;59 opt = std::move(opt).or_else([] { return std::optional<MoveOnly>{MoveOnly{}}; });60 std::move(opt).or_else([] {61 assert(false);62 return std::optional<MoveOnly>{};63 });64 }65#if TEST_STD_VER >= 2666 {67 int i = 2;68 std::optional<int&> opt;69 assert(opt.or_else([&] { return std::optional<int&>{i}; }) == i);70 int j = 3;71 opt = j;72 opt.or_else([] {73 assert(false);74 return std::optional<int&>{};75 });76 assert(opt == j);77 }78 {79 int i = 2;80 std::optional<int&> opt;81 assert(std::move(opt).or_else([&] { return std::optional<int&>{i}; }) == i);82 int j = 3;83 opt = j;84 std::move(opt).or_else([] {85 assert(false);86 return std::optional<int&>{};87 });88 assert(opt == j);89 }90#endif91 92 return true;93}94 95int main(int, char**) {96 test();97 static_assert(test());98 return 0;99}100