1acce2a31Syronglin //===----------------------------------------------------------------------===//
2acce2a31Syronglin //
3acce2a31Syronglin // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4acce2a31Syronglin // See https://llvm.org/LICENSE.txt for license information.
5acce2a31Syronglin // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6acce2a31Syronglin //
7acce2a31Syronglin //===----------------------------------------------------------------------===//
8acce2a31Syronglin
9acce2a31Syronglin // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
10acce2a31Syronglin
11acce2a31Syronglin // <expected>
12acce2a31Syronglin
13acce2a31Syronglin // template<class F> constexpr auto and_then(F&& f) &;
14acce2a31Syronglin // template<class F> constexpr auto and_then(F&& f) const &;
15acce2a31Syronglin // template<class F> constexpr auto and_then(F&& f) &&;
16acce2a31Syronglin // template<class F> constexpr auto and_then(F&& f) const &&;
17acce2a31Syronglin
18acce2a31Syronglin #include <expected>
19acce2a31Syronglin #include <concepts>
20acce2a31Syronglin #include <cassert>
21acce2a31Syronglin #include <memory>
22acce2a31Syronglin #include <type_traits>
23acce2a31Syronglin #include <utility>
24acce2a31Syronglin
25acce2a31Syronglin struct NonCopyable {
NonCopyableNonCopyable26acce2a31Syronglin constexpr NonCopyable(int) {}
27acce2a31Syronglin NonCopyable(const NonCopyable&) = delete;
28acce2a31Syronglin };
29acce2a31Syronglin
30acce2a31Syronglin struct NonMovable {
NonMovableNonMovable31acce2a31Syronglin constexpr NonMovable(int) {}
32acce2a31Syronglin NonMovable(NonMovable&&) = delete;
33acce2a31Syronglin };
34acce2a31Syronglin
35acce2a31Syronglin template <class E, class F>
36acce2a31Syronglin concept has_and_then =
37acce2a31Syronglin requires(E&& e, F&& f) {
38acce2a31Syronglin { std::forward<E>(e).and_then(std::forward<F>(f)) };
39acce2a31Syronglin };
40acce2a31Syronglin
return_int()41acce2a31Syronglin std::expected<void, int> return_int() { return {}; }
return_noncopyable()42acce2a31Syronglin std::expected<void, NonCopyable> return_noncopyable() { return {}; }
return_nonmovable()43acce2a31Syronglin std::expected<void, NonMovable> return_nonmovable() { return {}; }
44acce2a31Syronglin
45acce2a31Syronglin static_assert(has_and_then<std::expected<void, int>&, decltype(return_int)>);
46acce2a31Syronglin static_assert(!has_and_then<std::expected<void, NonCopyable>&, decltype(return_noncopyable)>);
47acce2a31Syronglin static_assert(has_and_then<const std::expected<void, int>&, decltype(return_int)>);
48acce2a31Syronglin static_assert(!has_and_then<const std::expected<void, NonCopyable>&, decltype(return_noncopyable)>);
49acce2a31Syronglin static_assert(has_and_then<std::expected<void, int>&&, decltype(return_int)>);
50acce2a31Syronglin static_assert(!has_and_then<std::expected<void, NonMovable>&&, decltype(return_nonmovable)>);
51acce2a31Syronglin static_assert(has_and_then<const std::expected<void, int>&&, decltype(return_int)>);
52acce2a31Syronglin static_assert(!has_and_then<const std::expected<void, NonMovable>&&, decltype(return_nonmovable)>);
53acce2a31Syronglin
54acce2a31Syronglin // [LWG 3877] https://cplusplus.github.io/LWG/issue3877, check constraint failing but not compile error inside the function body.
55acce2a31Syronglin static_assert(!has_and_then<const std::expected<int, std::unique_ptr<int>>&, int()>);
56acce2a31Syronglin static_assert(!has_and_then<const std::expected<int, std::unique_ptr<int>>&&, int()>);
57acce2a31Syronglin
test_val_types()58acce2a31Syronglin constexpr void test_val_types() {
59acce2a31Syronglin // Test & overload
60acce2a31Syronglin {
61*bf95a0cdSStephan T. Lavavej auto l = []() -> std::expected<int, int> { return 2; };
62acce2a31Syronglin std::expected<void, int> v;
63acce2a31Syronglin std::same_as<std::expected<int, int>> decltype(auto) val = v.and_then(l);
64acce2a31Syronglin assert(val == 2);
65acce2a31Syronglin }
66acce2a31Syronglin
67acce2a31Syronglin // Test const& overload
68acce2a31Syronglin {
69*bf95a0cdSStephan T. Lavavej auto l = []() -> std::expected<int, int> { return 2; };
70acce2a31Syronglin const std::expected<void, int> v;
71acce2a31Syronglin assert(v.and_then(l).value() == 2);
72acce2a31Syronglin static_assert(std::is_same_v< decltype(v.and_then(l)), std::expected<int, int>>);
73acce2a31Syronglin }
74acce2a31Syronglin
75acce2a31Syronglin // Test && overload
76acce2a31Syronglin {
77*bf95a0cdSStephan T. Lavavej auto l = []() -> std::expected<int, int> { return 2; };
78acce2a31Syronglin std::expected<void, int> v;
79acce2a31Syronglin std::same_as<std::expected<int, int>> decltype(auto) val = std::move(v).and_then(l);
80acce2a31Syronglin assert(val == 2);
81acce2a31Syronglin }
82acce2a31Syronglin
83acce2a31Syronglin // Test const&& overload
84acce2a31Syronglin {
85*bf95a0cdSStephan T. Lavavej auto l = []() -> std::expected<int, int> { return 2; };
86acce2a31Syronglin const std::expected<void, int> v;
87acce2a31Syronglin std::same_as<std::expected<int, int>> decltype(auto) val = std::move(v).and_then(l);
88acce2a31Syronglin assert(val == 2);
89acce2a31Syronglin }
90acce2a31Syronglin }
91acce2a31Syronglin
test_fail()92acce2a31Syronglin constexpr void test_fail() {
93acce2a31Syronglin // Test & overload
94acce2a31Syronglin {
95*bf95a0cdSStephan T. Lavavej auto f = []() -> std::expected<int, int> {
96acce2a31Syronglin assert(false);
97acce2a31Syronglin return 0;
98acce2a31Syronglin };
99acce2a31Syronglin std::expected<void, int> v(std::unexpected<int>(2));
100acce2a31Syronglin std::same_as<std::expected<int, int>> decltype(auto) val = v.and_then(f);
101acce2a31Syronglin assert(val.error() == 2);
102acce2a31Syronglin }
103acce2a31Syronglin
104acce2a31Syronglin // Test const& overload
105acce2a31Syronglin {
106*bf95a0cdSStephan T. Lavavej auto f = []() -> std::expected<int, int> {
107acce2a31Syronglin assert(false);
108acce2a31Syronglin return 0;
109acce2a31Syronglin };
110acce2a31Syronglin const std::expected<void, int> v(std::unexpected<int>(2));
111acce2a31Syronglin std::same_as<std::expected<int, int>> decltype(auto) val = v.and_then(f);
112acce2a31Syronglin assert(val.error() == 2);
113acce2a31Syronglin }
114acce2a31Syronglin
115acce2a31Syronglin // Test && overload
116acce2a31Syronglin {
117*bf95a0cdSStephan T. Lavavej auto f = []() -> std::expected<int, int> {
118acce2a31Syronglin assert(false);
119acce2a31Syronglin return 0;
120acce2a31Syronglin };
121acce2a31Syronglin std::expected<void, int> v(std::unexpected<int>(2));
122acce2a31Syronglin std::same_as<std::expected<int, int>> decltype(auto) val = std::move(v).and_then(f);
123acce2a31Syronglin assert(val.error() == 2);
124acce2a31Syronglin }
125acce2a31Syronglin
126acce2a31Syronglin // Test const&& overload
127acce2a31Syronglin {
128*bf95a0cdSStephan T. Lavavej auto f = []() -> std::expected<int, int> {
129acce2a31Syronglin assert(false);
130acce2a31Syronglin return 0;
131acce2a31Syronglin };
132acce2a31Syronglin const std::expected<void, int> v(std::unexpected<int>(2));
133acce2a31Syronglin std::same_as<std::expected<int, int>> decltype(auto) val = std::move(v).and_then(f);
134acce2a31Syronglin assert(val.error() == 2);
135acce2a31Syronglin }
136acce2a31Syronglin }
137acce2a31Syronglin
test()138acce2a31Syronglin constexpr bool test() {
139acce2a31Syronglin test_fail();
140acce2a31Syronglin test_val_types();
141acce2a31Syronglin return true;
142acce2a31Syronglin }
143acce2a31Syronglin
main(int,char **)144acce2a31Syronglin int main(int, char**) {
145acce2a31Syronglin test();
146acce2a31Syronglin static_assert(test());
147acce2a31Syronglin
148acce2a31Syronglin return 0;
149acce2a31Syronglin }
150