brintos

brintos / llvm-project-archived public Read only

0
0
Text · 11.1 KiB · 3ac58b3 Raw
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