brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.3 KiB · b8ab466 Raw
173 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// constexpr expected(expected&& rhs) noexcept(see below);12//13// Constraints:14// - is_move_constructible_v<T> is true and15// - is_move_constructible_v<E> is true.16//17// Effects: If rhs.has_value() is true, direct-non-list-initializes val with std::move(*rhs).18// Otherwise, direct-non-list-initializes unex with std::move(rhs.error()).19//20// Postconditions: rhs.has_value() is unchanged; rhs.has_value() == this->has_value() is true.21//22// Throws: Any exception thrown by the initialization of val or unex.23//24// Remarks: The exception specification is equivalent to is_nothrow_move_constructible_v<T> && is_nothrow_move_constructible_v<E>.25//26// This constructor is trivial if27// - is_trivially_move_constructible_v<T> is true and28// - is_trivially_move_constructible_v<E> is true.29 30#include <cassert>31#include <expected>32#include <type_traits>33#include <utility>34 35#include "test_macros.h"36#include "../../types.h"37 38struct NonMovable {39  NonMovable(NonMovable&&) = delete;40};41 42struct MovableNonTrivial {43  int i;44  constexpr MovableNonTrivial(int ii) : i(ii) {}45  constexpr MovableNonTrivial(MovableNonTrivial&& o) : i(o.i) { o.i = 0; }46  friend constexpr bool operator==(const MovableNonTrivial&, const MovableNonTrivial&) = default;47};48 49struct MoveMayThrow {50  MoveMayThrow(MoveMayThrow&&) {}51};52 53// Test Constraints:54// - is_move_constructible_v<T> is true and55// - is_move_constructible_v<E> is true.56static_assert(std::is_move_constructible_v<std::expected<int, int>>);57static_assert(std::is_move_constructible_v<std::expected<MovableNonTrivial, int>>);58static_assert(std::is_move_constructible_v<std::expected<int, MovableNonTrivial>>);59static_assert(std::is_move_constructible_v<std::expected<MovableNonTrivial, MovableNonTrivial>>);60static_assert(!std::is_move_constructible_v<std::expected<NonMovable, int>>);61static_assert(!std::is_move_constructible_v<std::expected<int, NonMovable>>);62static_assert(!std::is_move_constructible_v<std::expected<NonMovable, NonMovable>>);63 64// Test: This constructor is trivial if65// - is_trivially_move_constructible_v<T> is true and66// - is_trivially_move_constructible_v<E> is true.67static_assert(std::is_trivially_move_constructible_v<std::expected<int, int>>);68static_assert(!std::is_trivially_move_constructible_v<std::expected<MovableNonTrivial, int>>);69static_assert(!std::is_trivially_move_constructible_v<std::expected<int, MovableNonTrivial>>);70static_assert(!std::is_trivially_move_constructible_v<std::expected<MovableNonTrivial, MovableNonTrivial>>);71 72// Test: The exception specification is equivalent to73// is_nothrow_move_constructible_v<T> && is_nothrow_move_constructible_v<E>.74static_assert(std::is_nothrow_move_constructible_v<std::expected<int, int>>);75static_assert(!std::is_nothrow_move_constructible_v<std::expected<MoveMayThrow, int>>);76static_assert(!std::is_nothrow_move_constructible_v<std::expected<int, MoveMayThrow>>);77static_assert(!std::is_nothrow_move_constructible_v<std::expected<MoveMayThrow, MoveMayThrow>>);78 79constexpr bool test() {80  // move the value non-trivial81  {82    std::expected<MovableNonTrivial, int> e1(5);83    auto e2 = std::move(e1);84    assert(e2.has_value());85    assert(e2.value().i == 5);86    assert(e1.has_value());87    assert(e1.value().i == 0);88  }89 90  // move the error non-trivial91  {92    std::expected<int, MovableNonTrivial> e1(std::unexpect, 5);93    auto e2 = std::move(e1);94    assert(!e2.has_value());95    assert(e2.error().i == 5);96    assert(!e1.has_value());97    assert(e1.error().i == 0);98  }99 100  // move the value trivial101  {102    std::expected<int, int> e1(5);103    auto e2 = std::move(e1);104    assert(e2.has_value());105    assert(e2.value() == 5);106    assert(e1.has_value());107  }108 109  // move the error trivial110  {111    std::expected<int, int> e1(std::unexpect, 5);112    auto e2 = std::move(e1);113    assert(!e2.has_value());114    assert(e2.error() == 5);115    assert(!e1.has_value());116  }117 118  // move TailClobbererNonTrivialMove as value119  {120    std::expected<TailClobbererNonTrivialMove<0>, bool> e1;121    auto e2 = std::move(e1);122    assert(e2.has_value());123    assert(e1.has_value());124  }125 126  // move TailClobbererNonTrivialMove as error127  {128    std::expected<bool, TailClobbererNonTrivialMove<1>> e1(std::unexpect);129    auto e2 = std::move(e1);130    assert(!e2.has_value());131    assert(!e1.has_value());132  }133 134  return true;135}136 137void testException() {138#ifndef TEST_HAS_NO_EXCEPTIONS139  struct Throwing {140    Throwing() = default;141    Throwing(Throwing&&) { throw Except{}; }142  };143 144  // throw on moving value145  {146    std::expected<Throwing, int> e1;147    try {148      [[maybe_unused]] auto e2 = std::move(e1);149      assert(false);150    } catch (Except) {151    }152  }153 154  // throw on moving error155  {156    std::expected<int, Throwing> e1(std::unexpect);157    try {158      [[maybe_unused]] auto e2 = std::move(e1);159      assert(false);160    } catch (Except) {161    }162  }163 164#endif // TEST_HAS_NO_EXCEPTIONS165}166 167int main(int, char**) {168  test();169  static_assert(test());170  testException();171  return 0;172}173