150 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// <expected>12 13// template<class F> constexpr auto and_then(F&& f) &;14// template<class F> constexpr auto and_then(F&& f) const &;15// template<class F> constexpr auto and_then(F&& f) &&;16// template<class F> constexpr auto and_then(F&& f) const &&;17 18#include <expected>19#include <concepts>20#include <cassert>21#include <memory>22#include <type_traits>23#include <utility>24 25struct NonCopyable {26 constexpr NonCopyable(int) {}27 NonCopyable(const NonCopyable&) = delete;28};29 30struct NonMovable {31 constexpr NonMovable(int) {}32 NonMovable(NonMovable&&) = delete;33};34 35template <class E, class F>36concept has_and_then =37 requires(E&& e, F&& f) {38 { std::forward<E>(e).and_then(std::forward<F>(f)) };39 };40 41std::expected<void, int> return_int() { return {}; }42std::expected<void, NonCopyable> return_noncopyable() { return {}; }43std::expected<void, NonMovable> return_nonmovable() { return {}; }44 45static_assert(has_and_then<std::expected<void, int>&, decltype(return_int)>);46static_assert(!has_and_then<std::expected<void, NonCopyable>&, decltype(return_noncopyable)>);47static_assert(has_and_then<const std::expected<void, int>&, decltype(return_int)>);48static_assert(!has_and_then<const std::expected<void, NonCopyable>&, decltype(return_noncopyable)>);49static_assert(has_and_then<std::expected<void, int>&&, decltype(return_int)>);50static_assert(!has_and_then<std::expected<void, NonMovable>&&, decltype(return_nonmovable)>);51static_assert(has_and_then<const std::expected<void, int>&&, decltype(return_int)>);52static_assert(!has_and_then<const std::expected<void, NonMovable>&&, decltype(return_nonmovable)>);53 54// [LWG 3877] https://cplusplus.github.io/LWG/issue3877, check constraint failing but not compile error inside the function body.55static_assert(!has_and_then<const std::expected<int, std::unique_ptr<int>>&, int()>);56static_assert(!has_and_then<const std::expected<int, std::unique_ptr<int>>&&, int()>);57 58constexpr void test_val_types() {59 // Test & overload60 {61 auto l = []() -> std::expected<int, int> { return 2; };62 std::expected<void, int> v;63 std::same_as<std::expected<int, int>> decltype(auto) val = v.and_then(l);64 assert(val == 2);65 }66 67 // Test const& overload68 {69 auto l = []() -> std::expected<int, int> { return 2; };70 const std::expected<void, int> v;71 assert(v.and_then(l).value() == 2);72 static_assert(std::is_same_v< decltype(v.and_then(l)), std::expected<int, int>>);73 }74 75 // Test && overload76 {77 auto l = []() -> std::expected<int, int> { return 2; };78 std::expected<void, int> v;79 std::same_as<std::expected<int, int>> decltype(auto) val = std::move(v).and_then(l);80 assert(val == 2);81 }82 83 // Test const&& overload84 {85 auto l = []() -> std::expected<int, int> { return 2; };86 const std::expected<void, int> v;87 std::same_as<std::expected<int, int>> decltype(auto) val = std::move(v).and_then(l);88 assert(val == 2);89 }90}91 92constexpr void test_fail() {93 // Test & overload94 {95 auto f = []() -> std::expected<int, int> {96 assert(false);97 return 0;98 };99 std::expected<void, int> v(std::unexpected<int>(2));100 std::same_as<std::expected<int, int>> decltype(auto) val = v.and_then(f);101 assert(val.error() == 2);102 }103 104 // Test const& overload105 {106 auto f = []() -> std::expected<int, int> {107 assert(false);108 return 0;109 };110 const std::expected<void, int> v(std::unexpected<int>(2));111 std::same_as<std::expected<int, int>> decltype(auto) val = v.and_then(f);112 assert(val.error() == 2);113 }114 115 // Test && overload116 {117 auto f = []() -> std::expected<int, int> {118 assert(false);119 return 0;120 };121 std::expected<void, int> v(std::unexpected<int>(2));122 std::same_as<std::expected<int, int>> decltype(auto) val = std::move(v).and_then(f);123 assert(val.error() == 2);124 }125 126 // Test const&& overload127 {128 auto f = []() -> std::expected<int, int> {129 assert(false);130 return 0;131 };132 const std::expected<void, int> v(std::unexpected<int>(2));133 std::same_as<std::expected<int, int>> decltype(auto) val = std::move(v).and_then(f);134 assert(val.error() == 2);135 }136}137 138constexpr bool test() {139 test_fail();140 test_val_types();141 return true;142}143 144int main(int, char**) {145 test();146 static_assert(test());147 148 return 0;149}150