brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.6 KiB · 2587ca6 Raw
241 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 or_else(F&& f) &;14// template<class F> constexpr auto or_else(F&& f) const &;15// template<class F> constexpr auto or_else(F&& f) &&;16// template<class F> constexpr auto or_else(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 83template <class E, class F>84concept has_or_else =85    requires(E&& e, F&& f) {86      { std::forward<E>(e).or_else(std::forward<F>(f)) };87    };88// clang-format off89// [LWG 3877] https://cplusplus.github.io/LWG/issue3877, check constraint failing but not compile error inside the function body.90static_assert(!has_or_else<const std::expected<std::unique_ptr<int>, int>&, int()>);91static_assert(!has_or_else<const std::expected<std::unique_ptr<int>, int>&&, int()>);92 93// [LWG 3983] https://cplusplus.github.io/LWG/issue3938, check std::expected monadic ops well-formed with move-only error_type.94static_assert(has_or_else<std::expected<int, MoveOnlyErrorType>&, std::expected<int, int>(MoveOnlyErrorType &)>);95static_assert(has_or_else<const std::expected<int, MoveOnlyErrorType>&, std::expected<int, int>(const MoveOnlyErrorType &)>);96static_assert(has_or_else<std::expected<int, MoveOnlyErrorType>&&, std::expected<int, int>(MoveOnlyErrorType&&)>);97static_assert(has_or_else<const std::expected<int, MoveOnlyErrorType>&&, std::expected<int, int>(const MoveOnlyErrorType&&)>);98 99constexpr void test_val_types() {100  // Test & overload101  {102    // Without & qualifier on F's operator()103    {104      std::expected<int, int> e(std::unexpected<int>(0));105      std::same_as<std::expected<int, int>> decltype(auto) val = e.or_else(LVal{});106      assert(val == 1);107    }108 109    // With & qualifier on F's operator110    {111      std::expected<int, int> e(std::unexpected<int>(0));112      RefQual l{};113      std::same_as<std::expected<int, int>> decltype(auto) val = e.or_else(l);114      assert(val == 1);115    }116  }117 118  // Test const& overload119  {120    // Without const& qualifier on F's operator()121    {122      const std::expected<int, int> e(std::unexpected<int>(0));123      std::same_as<std::expected<int, int>> decltype(auto) val = e.or_else(CLVal{});124      assert(val == 1);125    }126 127    // With const& qualifier on F's operator()128    {129      const std::expected<int, int> e(std::unexpected<int>(0));130      const CRefQual l{};131      std::same_as<std::expected<int, int>> decltype(auto) val = e.or_else(l);132      assert(val == 1);133    }134  }135 136  // Test && overload137  {138    // Without && qualifier on F's operator()139    {140      std::expected<int, int> e(std::unexpected<int>(0));141      std::same_as<std::expected<int, int>> decltype(auto) val = std::move(e).or_else(RVal{});142      assert(val == 1);143    }144 145    // With && qualifier on F's operator()146    {147      std::expected<int, int> e(std::unexpected<int>(0));148      std::same_as<std::expected<int, int>> decltype(auto) val = std::move(e).or_else(RVRefQual{});149      assert(val == 1);150    }151  }152 153  // Test const&& overload154  {155    // Without const&& qualifier on F's operator()156    {157      const std::expected<int, int> e(std::unexpected<int>(0));158      std::same_as<std::expected<int, int>> decltype(auto) val = std::move(e).or_else(CRVal{});159      assert(val == 1);160    }161 162    // With const&& qualifier on F's operator()163    {164      const std::expected<int, int> e(std::unexpected<int>(0));165      const RVCRefQual l{};166      std::same_as<std::expected<int, int>> decltype(auto) val = std::move(e).or_else(std::move(l));167      assert(val == 1);168    }169  }170}171// clang-format on172 173struct NonConst {174  std::expected<int, int> non_const() { return std::expected<int, int>(std::unexpect, 1); }175};176 177// check that the lambda body is not instantiated during overload resolution178constexpr void test_sfinae() {179  std::expected<int, NonConst> e{1};180  auto l = [](auto&& x) { return x.non_const(); };181  (void)e.or_else(l);182  (void)std::move(e).or_else(l);183}184 185constexpr void test_move_only_error_type() {186  // Test &187  {188      std::expected<int, MoveOnlyErrorType> e;189      auto l = [](MoveOnlyErrorType&) { return std::expected<int, int>{}; };190      (void)e.or_else(l);191  }192 193  // Test const&194  {195      const std::expected<int, MoveOnlyErrorType> e;196      auto l = [](const MoveOnlyErrorType&) { return std::expected<int, int>{}; };197      (void)e.or_else(l);198  }199 200  // Test &&201  {202      std::expected<int, MoveOnlyErrorType> e;203      auto l = [](MoveOnlyErrorType&&) { return std::expected<int, int>{}; };204      (void)std::move(e).or_else(l);205  }206 207  // Test const&&208  {209      const std::expected<int, MoveOnlyErrorType> e;210      auto l = [](const MoveOnlyErrorType&&) { return std::expected<int, int>{}; };211      (void)std::move(e).or_else(l);212  }213}214 215constexpr bool test() {216  test_sfinae();217  test_val_types();218  test_move_only_error_type();219 220  std::expected<int, int> e(1);221  const auto& ce = e;222 223  const auto never_called = [](int) {224    assert(false);225    return std::expected<int, int>();226  };227 228  (void)e.or_else(never_called);229  (void)std::move(e).or_else(never_called);230  (void)ce.or_else(never_called);231  (void)std::move(ce).or_else(never_called);232  return true;233}234 235int main(int, char**) {236  test();237  static_assert(test());238 239  return 0;240}241