brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.8 KiB · fe664df Raw
217 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// template<class U = T>12//   constexpr explicit(!is_convertible_v<U, T>) expected(U&& v);13//14// Constraints:15// - is_same_v<remove_cvref_t<U>, in_place_t> is false; and16// - is_same_v<expected, remove_cvref_t<U>> is false; and17// - is_same_v<remove_cvref_t<U>, unexpect_t> is false; and18// - remove_cvref_t<U> is not a specialization of unexpected; and19// - is_constructible_v<T, U> is true.20//21// Effects: Direct-non-list-initializes val with std::forward<U>(v).22//23// Postconditions: has_value() is true.24//25// Throws: Any exception thrown by the initialization of val.26 27#include <cassert>28#include <expected>29#include <type_traits>30#include <utility>31 32#include "MoveOnly.h"33#include "test_macros.h"34#include "../../types.h"35 36// Test Constraints:37static_assert(std::is_constructible_v<std::expected<int, int>, int>);38 39// is_same_v<remove_cvref_t<U>, in_place_t>40struct FromJustInplace {41  FromJustInplace(std::in_place_t);42};43static_assert(!std::is_constructible_v<std::expected<FromJustInplace, int>, std::in_place_t>);44static_assert(!std::is_constructible_v<std::expected<FromJustInplace, int>, std::in_place_t const&>);45 46// is_same_v<expected, remove_cvref_t<U>>47// Note that result is true because it is covered by the constructors that take expected48static_assert(std::is_constructible_v<std::expected<int, int>, std::expected<int, int>&>);49 50struct T {51  explicit T(auto) {}52};53struct E {54  E(int) {}55};56 57// is_same_v<remove_cvref_t<U>, unexpect_t> is false;58static_assert(!std::is_constructible_v<std::expected<T, E>, std::unexpect_t>);59 60// remove_cvref_t<U> is a specialization of unexpected61// Note that result is true because it is covered by the constructors that take unexpected62static_assert(std::is_constructible_v<std::expected<int, int>, std::unexpected<int>&>);63 64// !is_constructible_v<T, U>65struct foo {};66static_assert(!std::is_constructible_v<std::expected<int, int>, foo>);67 68// test explicit(!is_convertible_v<U, T>)69struct NotConvertible {70  explicit NotConvertible(int);71};72static_assert(std::is_convertible_v<int, std::expected<int, int>>);73static_assert(!std::is_convertible_v<int, std::expected<NotConvertible, int>>);74 75struct CopyOnly {76  int i;77  constexpr CopyOnly(int ii) : i(ii) {}78  CopyOnly(const CopyOnly&) = default;79  CopyOnly(CopyOnly&&)      = delete;80  friend constexpr bool operator==(const CopyOnly& mi, int ii) { return mi.i == ii; }81};82 83struct MoveOnly2 {84  int j;85  bool used_move1 = false;86  bool used_move2 = false;87 88  constexpr explicit MoveOnly2(int jj) : j(jj) {}89  constexpr MoveOnly2(const MoveOnly2&) = delete;90  constexpr MoveOnly2(MoveOnly2&& m) : j(m.j), used_move1(true) {}91  constexpr MoveOnly2(const MoveOnly2&& m) : j(m.j), used_move2(true) {}92};93 94struct BaseError {};95struct DerivedError : BaseError {};96 97template <class T, class E = int>98constexpr void testInt() {99  std::expected<T, E> e(5);100  assert(e.has_value());101  assert(e.value() == 5);102}103 104template <class T, class E = int>105constexpr void testLValue() {106  T t(5);107  std::expected<T, E> e(t);108  assert(e.has_value());109  assert(e.value() == 5);110}111 112template <class T, class E = int>113constexpr void testRValue() {114  std::expected<T, E> e(T(5));115  assert(e.has_value());116  assert(e.value() == 5);117}118 119constexpr bool test() {120  testInt<int>();121  testInt<CopyOnly>();122  testInt<MoveOnly>();123  testInt<TailClobberer<0>, bool>();124  testLValue<int>();125  testLValue<CopyOnly>();126  testLValue<TailClobberer<0>, bool>();127  testRValue<int>();128  testRValue<MoveOnly>();129  testRValue<TailClobberer<0>, bool>();130 131  // Test default template argument.132  // Without it, the template parameter cannot be deduced from an initializer list133  {134    struct Bar {135      int i;136      int j;137      constexpr Bar(int ii, int jj) : i(ii), j(jj) {}138    };139 140    std::expected<Bar, int> e({5, 6});141    assert(e.value().i == 5);142    assert(e.value().j == 6);143  }144 145  // https://cplusplus.github.io/LWG/issue3836146 147  // Test &148  {149    std::expected<bool, DerivedError> e1(false);150    std::expected<bool, BaseError> e2(e1);151    assert(e2.has_value());152    assert(!e2.value()); // yes, e2 holds "false" since LWG3836153  }154 155  // Test &&156  {157    std::expected<bool, DerivedError> e1(false);158    std::expected<bool, BaseError> e2(std::move(e1));159    assert(e2.has_value());160    assert(!e2.value()); // yes, e2 holds "false" since LWG3836161  }162 163  // Test const&164  {165    const std::expected<bool, DerivedError> e1(false);166    std::expected<bool, BaseError> e2(e1);167    assert(e2.has_value());168    assert(!e2.value()); // yes, e2 holds "false" since LWG3836169  }170 171  // Test const&&172  {173    const std::expected<bool, DerivedError> e1(false);174    std::expected<bool, BaseError> e2(std::move(e1));175    assert(e2.has_value());176    assert(!e2.value()); // yes, e2 holds "false" since LWG3836177  }178 179  // Check move constructor selection180  {181    MoveOnly2 t{1};182    std::expected<MoveOnly2, BaseError> e1(std::move(t));183    assert(e1.has_value());184    assert(e1.value().used_move1 == true);185    assert(e1.value().j == 1);186  }187  {188    const MoveOnly2 t2{2};189    std::expected<MoveOnly2, BaseError> e1(std::move(t2));190    assert(e1.has_value());191    assert(e1.value().used_move2 == true);192    assert(e1.value().j == 2);193  }194  return true;195}196 197void testException() {198#ifndef TEST_HAS_NO_EXCEPTIONS199  struct Throwing {200    Throwing(int) { throw Except{}; };201  };202 203  try {204    std::expected<Throwing, int> u(5);205    assert(false);206  } catch (Except) {207  }208#endif // TEST_HAS_NO_EXCEPTIONS209}210 211int main(int, char**) {212  test();213  static_assert(test());214  testException();215  return 0;216}217