brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.7 KiB · 97c1e4a Raw
276 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// GCC has a issue for `Guaranteed copy elision for potentially-overlapping non-static data members`,12// please refer to: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=9899513// XFAIL: gcc-14, gcc-1514 15// <expected>16 17// template<class F> constexpr auto transform(F&& f) &;18// template<class F> constexpr auto transform(F&& f) const &;19// template<class F> constexpr auto transform(F&& f) &&;20// template<class F> constexpr auto transform(F&& f) const &&;21 22#include <expected>23#include <concepts>24#include <cassert>25#include <memory>26#include <type_traits>27#include <utility>28 29#include "../../types.h"30 31struct LVal {32  constexpr int operator()(int&) { return 1; }33  int operator()(const int&)  = delete;34  int operator()(int&&)       = delete;35  int operator()(const int&&) = delete;36};37 38struct CLVal {39  int operator()(int&) = delete;40  constexpr int operator()(const int&) { return 1; }41  int operator()(int&&)       = delete;42  int operator()(const int&&) = delete;43};44 45struct RVal {46  int operator()(int&)       = delete;47  int operator()(const int&) = delete;48  constexpr int operator()(int&&) { return 1; }49  int operator()(const int&&) = delete;50};51 52struct CRVal {53  int operator()(int&)       = delete;54  int operator()(const int&) = delete;55  int operator()(int&&)      = delete;56  constexpr int operator()(const int&&) { return 1; }57};58 59struct RefQual {60  constexpr int operator()(int) & { return 1; }61  int operator()(int) const&  = delete;62  int operator()(int) &&      = delete;63  int operator()(int) const&& = delete;64};65 66struct CRefQual {67  int operator()(int) & = delete;68  constexpr int operator()(int) const& { return 1; }69  int operator()(int) &&      = delete;70  int operator()(int) const&& = delete;71};72 73struct RVRefQual {74  int operator()(int) &      = delete;75  int operator()(int) const& = delete;76  constexpr int operator()(int) && { return 1; }77  int operator()(int) const&& = delete;78};79 80struct RVCRefQual {81  int operator()(int) &      = delete;82  int operator()(int) const& = delete;83  int operator()(int) &&     = delete;84  constexpr int operator()(int) const&& { return 1; }85};86 87struct NonCopy {88  int value;89  constexpr explicit NonCopy(int val) : value(val) {}90  NonCopy(const NonCopy&) = delete;91};92 93struct NonConst {94  int non_const() { return 1; }95};96 97template <class E, class F>98concept has_transform =99    requires(E&& e, F&& f) {100      { std::forward<E>(e).transform(std::forward<F>(f)) };101    };102 103// clang-format off104// [LWG 3877] https://cplusplus.github.io/LWG/issue3877, check constraint failing but not compile error inside the function body.105static_assert(!has_transform<const std::expected<int, std::unique_ptr<int>>&, int()>);106static_assert(!has_transform<const std::expected<int, std::unique_ptr<int>>&&, int()>);107 108// [LWG 3983] https://cplusplus.github.io/LWG/issue3938, check std::expected monadic ops well-formed with move-only error_type.109// There are no effects for `&` and `const &` overload, because the constraints requires is_constructible_v<E, decltype(error())> is true.110static_assert(has_transform<std::expected<int, MoveOnlyErrorType>&&, int(int)>);111static_assert(has_transform<const std::expected<int, MoveOnlyErrorType>&&, int(const int)>);112 113constexpr void test_val_types() {114  // Test & overload115  {116    // Without & qualifier on F's operator()117    {118      std::expected<int, int> e(0);119      std::same_as<std::expected<int, int>> decltype(auto) val = e.transform(LVal{});120      assert(val == 1);121    }122 123    // With & qualifier on F's operator()124    {125      std::expected<int, int> e(0);126      RefQual l{};127      std::same_as<std::expected<int, int>> decltype(auto) val = e.transform(l);128      assert(val == 1);129    }130  }131 132  // Test const& overload133  {134    // Without & qualifier on F's operator()135    {136      const std::expected<int, int> e(0);137      std::same_as<std::expected<int, int>> decltype(auto) val = e.transform(CLVal{});138      assert(val == 1);139    }140 141    // With & qualifier on F's operator()142    {143      const std::expected<int, int> e(0);144      const CRefQual l{};145      std::same_as<std::expected<int, int>> decltype(auto) val = e.transform(l);146      assert(val == 1);147    }148  }149 150  // Test && overload151  {152    // Without & qualifier on F's operator()153    {154      std::expected<int, int> e(0);155      std::same_as<std::expected<int, int>> decltype(auto) val = std::move(e).transform(RVal{});156      assert(val == 1);157    }158 159    // With & qualifier on F's operator()160    {161      std::expected<int, int> e(0);162      std::same_as<std::expected<int, int>> decltype(auto) val = std::move(e).transform(RVRefQual{});163      assert(val == 1);164    }165  }166 167  // Test const&& overload168  {169    // Without & qualifier on F's operator()170    {171      const std::expected<int, int> e(0);172      std::same_as<std::expected<int, int>> decltype(auto) val = std::move(e).transform(CRVal{});173      assert(val == 1);174    }175 176    // With & qualifier on F's operator()177    {178      const std::expected<int, int> e(0);179      const RVCRefQual l{};180      std::same_as<std::expected<int, int>> decltype(auto) val = e.transform(std::move(l));181      assert(val == 1);182    }183  }184}185// clang-format on186 187constexpr void test_take_val_return_void() {188  std::expected<int, int> e(1);189  int val = 0;190  (void)e.transform([&val]<typename T>(T&&) -> void {191    static_assert(std::is_same_v<T, int&>);192    assert(val == 0);193    val = 1;194  });195  assert(val == 1);196  (void)std::move(e).transform([&val]<typename T>(T&&) -> void {197    static_assert(std::is_same_v<T, int>);198    assert(val == 1);199    val = 2;200  });201 202  const auto& ce = e;203  assert(val == 2);204  (void)ce.transform([&val]<typename T>(T&&) -> void {205    static_assert(std::is_same_v<T, const int&>);206    assert(val == 2);207    val = 3;208  });209  assert(val == 3);210  (void)std::move(ce).transform([&val]<typename T>(T&&) -> void {211    static_assert(std::is_same_v<T, const int>);212    assert(val == 3);213    val = 4;214  });215  assert(val == 4);216}217 218// check val member is direct-non-list-initialized with invoke(std::forward<F>(f), value())219constexpr void test_direct_non_list_init() {220  auto xform = [](int i) { return NonCopy(i); };221  std::expected<int, int> e(2);222  std::expected<NonCopy, int> n = e.transform(xform);223  assert(n.value().value == 2);224}225 226// check that the lambda body is not instantiated during overload resolution227constexpr void test_sfinae() {228  std::expected<NonConst, int> e(std::unexpected<int>(2));229  auto l = [](auto&& x) { return x.non_const(); };230  (void)e.transform(l);231  (void)std::move(e).transform(l);232 233  std::expected<int, int> e1(std::unexpected<int>(1));234  const auto& ce1         = e1;235  const auto never_called = [](int) {236    assert(false);237    return std::expected<int, int>();238  };239 240  (void)e1.transform(never_called);241  (void)std::move(e1).transform(never_called);242  (void)ce1.transform(never_called);243  (void)std::move(ce1).transform(never_called);244}245 246constexpr void test_move_only_error_type() {247  // Test &&248  {249      std::expected<int, MoveOnlyErrorType> e;250      auto l = [](int) { return 0; };251      (void)std::move(e).transform(l);252  }253 254  // Test const&&255  {256      const std::expected<int, MoveOnlyErrorType> e;257      auto l = [](const int) { return 0; };258      (void)std::move(e).transform(l);259  }260}261 262constexpr bool test() {263  test_sfinae();264  test_val_types();265  test_direct_non_list_init();266  test_move_only_error_type();267  return true;268}269 270int main(int, char**) {271  test();272  static_assert(test());273 274  return 0;275}276