brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.6 KiB · e4a384a Raw
150 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 <expected>19#include <concepts>20#include <cassert>21#include <memory>22#include <type_traits>23#include <utility>24 25struct NonCopyable {26  constexpr NonCopyable(int) {}27  NonCopyable(const NonCopyable&) = delete;28};29 30struct NonMovable {31  constexpr NonMovable(int) {}32  NonMovable(NonMovable&&) = delete;33};34 35template <class E, class F>36concept has_and_then =37    requires(E&& e, F&& f) {38      { std::forward<E>(e).and_then(std::forward<F>(f)) };39    };40 41std::expected<void, int> return_int() { return {}; }42std::expected<void, NonCopyable> return_noncopyable() { return {}; }43std::expected<void, NonMovable> return_nonmovable() { return {}; }44 45static_assert(has_and_then<std::expected<void, int>&, decltype(return_int)>);46static_assert(!has_and_then<std::expected<void, NonCopyable>&, decltype(return_noncopyable)>);47static_assert(has_and_then<const std::expected<void, int>&, decltype(return_int)>);48static_assert(!has_and_then<const std::expected<void, NonCopyable>&, decltype(return_noncopyable)>);49static_assert(has_and_then<std::expected<void, int>&&, decltype(return_int)>);50static_assert(!has_and_then<std::expected<void, NonMovable>&&, decltype(return_nonmovable)>);51static_assert(has_and_then<const std::expected<void, int>&&, decltype(return_int)>);52static_assert(!has_and_then<const std::expected<void, NonMovable>&&, decltype(return_nonmovable)>);53 54// [LWG 3877] https://cplusplus.github.io/LWG/issue3877, check constraint failing but not compile error inside the function body.55static_assert(!has_and_then<const std::expected<int, std::unique_ptr<int>>&, int()>);56static_assert(!has_and_then<const std::expected<int, std::unique_ptr<int>>&&, int()>);57 58constexpr void test_val_types() {59  // Test & overload60  {61    auto l = []() -> std::expected<int, int> { return 2; };62    std::expected<void, int> v;63    std::same_as<std::expected<int, int>> decltype(auto) val = v.and_then(l);64    assert(val == 2);65  }66 67  // Test const& overload68  {69    auto l = []() -> std::expected<int, int> { return 2; };70    const std::expected<void, int> v;71    assert(v.and_then(l).value() == 2);72    static_assert(std::is_same_v< decltype(v.and_then(l)), std::expected<int, int>>);73  }74 75  // Test && overload76  {77    auto l = []() -> std::expected<int, int> { return 2; };78    std::expected<void, int> v;79    std::same_as<std::expected<int, int>> decltype(auto) val = std::move(v).and_then(l);80    assert(val == 2);81  }82 83  // Test const&& overload84  {85    auto l = []() -> std::expected<int, int> { return 2; };86    const std::expected<void, int> v;87    std::same_as<std::expected<int, int>> decltype(auto) val = std::move(v).and_then(l);88    assert(val == 2);89  }90}91 92constexpr void test_fail() {93  // Test & overload94  {95    auto f = []() -> std::expected<int, int> {96      assert(false);97      return 0;98    };99    std::expected<void, int> v(std::unexpected<int>(2));100    std::same_as<std::expected<int, int>> decltype(auto) val = v.and_then(f);101    assert(val.error() == 2);102  }103 104  // Test const& overload105  {106    auto f = []() -> std::expected<int, int> {107      assert(false);108      return 0;109    };110    const std::expected<void, int> v(std::unexpected<int>(2));111    std::same_as<std::expected<int, int>> decltype(auto) val = v.and_then(f);112    assert(val.error() == 2);113  }114 115  // Test && overload116  {117    auto f = []() -> std::expected<int, int> {118      assert(false);119      return 0;120    };121    std::expected<void, int> v(std::unexpected<int>(2));122    std::same_as<std::expected<int, int>> decltype(auto) val = std::move(v).and_then(f);123    assert(val.error() == 2);124  }125 126  // Test const&& overload127  {128    auto f = []() -> std::expected<int, int> {129      assert(false);130      return 0;131    };132    const std::expected<void, int> v(std::unexpected<int>(2));133    std::same_as<std::expected<int, int>> decltype(auto) val = std::move(v).and_then(f);134    assert(val.error() == 2);135  }136}137 138constexpr bool test() {139  test_fail();140  test_val_types();141  return true;142}143 144int main(int, char**) {145  test();146  static_assert(test());147 148  return 0;149}150