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
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 & overload
60 {
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& overload
68 {
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 && overload
76 {
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&& overload
84 {
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 & overload
94 {
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& overload
105 {
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 && overload
116 {
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&& overload
127 {
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

source code of libcxx/test/std/utilities/expected/expected.void/monadic/and_then.pass.cpp