313 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 <cassert>19#include <concepts>20#include <expected>21#include <memory>22#include <type_traits>23#include <utility>24 25#include "../../types.h"26 27struct LVal {28 constexpr std::expected<int, int> operator()(int&) { return 1; }29 std::expected<int, int> operator()(const int&) = delete;30 std::expected<int, int> operator()(int&&) = delete;31 std::expected<int, int> operator()(const int&&) = delete;32};33 34struct CLVal {35 std::expected<int, int> operator()(int&) = delete;36 constexpr std::expected<int, int> operator()(const int&) { return 1; }37 std::expected<int, int> operator()(int&&) = delete;38 std::expected<int, int> operator()(const int&&) = delete;39};40 41struct RVal {42 std::expected<int, int> operator()(int&) = delete;43 std::expected<int, int> operator()(const int&) = delete;44 constexpr std::expected<int, int> operator()(int&&) { return 1; }45 std::expected<int, int> operator()(const int&&) = delete;46};47 48struct CRVal {49 std::expected<int, int> operator()(int&) = delete;50 std::expected<int, int> operator()(const int&) = delete;51 std::expected<int, int> operator()(int&&) = delete;52 constexpr std::expected<int, int> operator()(const int&&) { return 1; }53};54 55struct RefQual {56 constexpr std::expected<int, int> operator()(int) & { return 1; }57 std::expected<int, int> operator()(int) const& = delete;58 std::expected<int, int> operator()(int) && = delete;59 std::expected<int, int> operator()(int) const&& = delete;60};61 62struct CRefQual {63 std::expected<int, int> operator()(int) & = delete;64 constexpr std::expected<int, int> operator()(int) const& { return 1; }65 std::expected<int, int> operator()(int) && = delete;66 std::expected<int, int> operator()(int) const&& = delete;67};68 69struct RVRefQual {70 std::expected<int, int> operator()(int) & = delete;71 std::expected<int, int> operator()(int) const& = delete;72 constexpr std::expected<int, int> operator()(int) && { return 1; }73 std::expected<int, int> operator()(int) const&& = delete;74};75 76struct RVCRefQual {77 std::expected<int, int> operator()(int) & = delete;78 std::expected<int, int> operator()(int) const& = delete;79 std::expected<int, int> operator()(int) && = delete;80 constexpr std::expected<int, int> operator()(int) const&& { return 1; }81};82 83struct UnexpectedLVal {84 constexpr std::expected<int, int> operator()(int&) { return std::expected<int, int>(std::unexpected<int>(5)); }85 std::expected<int, int> operator()(const int&) = delete;86 std::expected<int, int> operator()(int&&) = delete;87 std::expected<int, int> operator()(const int&&) = delete;88};89 90struct UnexpectedCLVal {91 std::expected<int, int> operator()(int&) = delete;92 constexpr std::expected<int, int> operator()(const int&) { return std::expected<int, int>(std::unexpected<int>(5)); }93 std::expected<int, int> operator()(int&&) = delete;94 std::expected<int, int> operator()(const int&&) = delete;95};96 97struct UnexpectedRVal {98 std::expected<int, int> operator()(int&) = delete;99 std::expected<int, int> operator()(const int&) = delete;100 constexpr std::expected<int, int> operator()(int&&) { return std::expected<int, int>(std::unexpected<int>(5)); }101 std::expected<int, int> operator()(const int&&) = delete;102};103 104struct UnexpectedCRVal {105 std::expected<int, int> operator()(int&) = delete;106 std::expected<int, int> operator()(const int&) = delete;107 std::expected<int, int> operator()(int&&) = delete;108 constexpr std::expected<int, int> operator()(const int&&) { return std::expected<int, int>(std::unexpected<int>(5)); }109};110 111struct UnexpectedRefQual {112 constexpr std::expected<int, int> operator()(int) & { return std::expected<int, int>(std::unexpected<int>(5)); }113 std::expected<int, int> operator()(int) const& = delete;114 std::expected<int, int> operator()(int) && = delete;115 std::expected<int, int> operator()(int) const&& = delete;116};117 118struct UnexpectedCRefQual {119 std::expected<int, int> operator()(int) & = delete;120 constexpr std::expected<int, int> operator()(int) const& { return std::expected<int, int>(std::unexpected<int>(5)); }121 std::expected<int, int> operator()(int) && = delete;122 std::expected<int, int> operator()(int) const&& = delete;123};124 125struct UnexpectedRVRefQual {126 std::expected<int, int> operator()(int) & = delete;127 std::expected<int, int> operator()(int) const& = delete;128 constexpr std::expected<int, int> operator()(int) && { return std::expected<int, int>(std::unexpected<int>(5)); }129 std::expected<int, int> operator()(int) const&& = delete;130};131 132struct UnexpectedRVCRefQual {133 std::expected<int, int> operator()(int) & = delete;134 std::expected<int, int> operator()(int) const& = delete;135 std::expected<int, int> operator()(int) && = delete;136 constexpr std::expected<int, int> operator()(int) const&& { return std::expected<int, int>(std::unexpected<int>(5)); }137};138 139struct NonCopyable {140 constexpr NonCopyable(int) {}141 NonCopyable(const NonCopyable&) = delete;142};143 144struct NonMovable {145 constexpr NonMovable(int) {}146 NonMovable(NonMovable&&) = delete;147};148 149struct NonConst {150 std::expected<int, int> non_const() { return 1; }151};152 153template <class E, class F>154concept has_and_then = requires(E&& e, F&& f) {155 {std::forward<E>(e).and_then(std::forward<F>(f))};156};157 158// clang-format off159static_assert( has_and_then<std::expected<int, int>&, std::expected<int, int>(int&)>);160static_assert(!has_and_then<std::expected<int, NonCopyable>&, std::expected<int, NonCopyable>(int&)>);161static_assert( has_and_then<const std::expected<int, int>&, std::expected<int, int>(const int&)>);162static_assert(!has_and_then<const std::expected<int, NonCopyable>&, std::expected<int, NonCopyable>(const int&)>);163static_assert( has_and_then<std::expected<int, int>&&, std::expected<int, int>(int)>);164static_assert(!has_and_then<std::expected<int, NonMovable>&&, std::expected<int, NonMovable>(int)>);165static_assert( has_and_then<const std::expected<int, int>&&, std::expected<int, int>(const int)>);166static_assert(!has_and_then<const std::expected<int, NonMovable>&&, std::expected<int, NonMovable>(const int)>);167 168// [LWG 3877] https://cplusplus.github.io/LWG/issue3877, check constraint failing but not compile error inside the function body.169static_assert(!has_and_then<const std::expected<int, std::unique_ptr<int>>&, int()>);170static_assert(!has_and_then<const std::expected<int, std::unique_ptr<int>>&&, int()>);171 172// [LWG 3983] https://cplusplus.github.io/LWG/issue3938, check std::expected monadic ops well-formed with move-only error_type.173// There are no effects for `&` and `const &` overload, because the constraints requires is_constructible_v<E, decltype(error())> is true.174static_assert(has_and_then<std::expected<int, MoveOnlyErrorType>&&, std::expected<int, MoveOnlyErrorType>(int)>);175static_assert(has_and_then<const std::expected<int, MoveOnlyErrorType>&&, std::expected<int, MoveOnlyErrorType>(const int)>);176 177constexpr void test_val_types() {178 // Test & overload179 {180 // Without & qualifier on F's operator()181 {182 std::expected<int, int> e{0};183 std::same_as<std::expected<int, int>> decltype(auto) val = e.and_then(LVal{});184 assert(val == 1);185 assert(e.and_then(UnexpectedLVal{}).error() == 5);186 }187 188 // With & qualifier on F's operator()189 {190 std::expected<int, int> e{0};191 RefQual l{};192 std::same_as<std::expected<int, int>> decltype(auto) val = e.and_then(l);193 assert(val == 1);194 UnexpectedRefQual nl{};195 assert(e.and_then(nl).error() == 5);196 }197 }198 199 // Test const& overload200 {201 // Without & qualifier on F's operator()202 {203 const std::expected<int, int> e{0};204 std::same_as<std::expected<int, int>> decltype(auto) val = e.and_then(CLVal{});205 assert(val == 1);206 assert(e.and_then(UnexpectedCLVal{}).error() == 5);207 }208 209 // With & qualifier on F's operator()210 {211 const std::expected<int, int> e{0};212 const CRefQual l{};213 std::same_as<std::expected<int, int>> decltype(auto) val = e.and_then(l);214 assert(val == 1);215 const UnexpectedCRefQual nl{};216 assert(e.and_then(nl).error() == 5);217 }218 }219 220 // Test && overload221 {222 // Without & qualifier on F's operator()223 {224 std::expected<int, int> e{0};225 std::same_as<std::expected<int, int>> decltype(auto) val = std::move(e).and_then(RVal{});226 assert(val == 1);227 assert(std::move(e).and_then(UnexpectedRVal{}).error() == 5);228 }229 230 // With & qualifier on F's operator()231 {232 std::expected<int, int> e{0};233 std::same_as<std::expected<int, int>> decltype(auto) val = std::move(e).and_then(RVRefQual{});234 assert(val == 1);235 assert(e.and_then(UnexpectedRVRefQual{}).error() == 5);236 }237 }238 239 // Test const&& overload240 {241 // Without & qualifier on F's operator()242 {243 const std::expected<int, int> e{0};244 std::same_as<std::expected<int, int>> decltype(auto) val = std::move(e).and_then(CRVal{});245 assert(val == 1);246 assert(std::move(e).and_then(UnexpectedCRVal{}).error() == 5);247 }248 249 // With & qualifier on F's operator()250 {251 const std::expected<int, int> e{0};252 const RVCRefQual l{};253 std::same_as<std::expected<int, int>> decltype(auto) val = std::move(e).and_then(std::move(l));254 assert(val == 1);255 const UnexpectedRVCRefQual nl{};256 assert(std::move(e).and_then(std::move(nl)).error() == 5);257 }258 }259}260// clang-format on261 262// check that the lambda body is not instantiated during overload resolution263constexpr void test_sfinae() {264 std::expected<NonConst, int> e(std::unexpected<int>(2));265 auto l = [](auto&& x) { return x.non_const(); };266 (void)e.and_then(l);267 (void)std::move(e).and_then(l);268}269 270constexpr void test_move_only_error_type() {271 // Test &&272 {273 std::expected<int, MoveOnlyErrorType> e;274 auto l = [](int) { return std::expected<int, MoveOnlyErrorType>{}; };275 (void)std::move(e).and_then(l);276 }277 278 // Test const&&279 {280 const std::expected<int, MoveOnlyErrorType> e;281 auto l = [](const int) { return std::expected<int, MoveOnlyErrorType>{}; };282 (void)std::move(e).and_then(l);283 }284}285 286constexpr bool test() {287 test_sfinae();288 test_val_types();289 test_move_only_error_type();290 291 std::expected<int, int> e(std::unexpected<int>(1));292 const auto& ce = e;293 294 const auto never_called = [](int) {295 assert(false);296 return std::expected<int, int>();297 };298 299 (void)e.and_then(never_called);300 (void)std::move(e).and_then(never_called);301 (void)ce.and_then(never_called);302 (void)std::move(ce).and_then(never_called);303 304 return true;305}306 307int main(int, char**) {308 test();309 static_assert(test());310 311 return 0;312}313