1//===----------------------------------------------------------------------===//
2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3// See https://llvm.org/LICENSE.txt for license information.
4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5//
6//===----------------------------------------------------------------------===//
7
8// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
9
10// constexpr expected(expected&& rhs) noexcept(is_nothrow_move_constructible_v<E>);
11//
12// Constraints: is_move_constructible_v<E> is true.
13//
14// Effects: If rhs.has_value() is false, direct-non-list-initializes unex with std::move(rhs.error()).
15//
16// Postconditions: rhs.has_value() is unchanged; rhs.has_value() == this->has_value() is true.
17//
18// Throws: Any exception thrown by the initialization of unex.
19//
20// Remarks: This constructor is trivial if is_trivially_move_constructible_v<E> is true.
21
22#include <cassert>
23#include <expected>
24#include <type_traits>
25#include <utility>
26
27#include "test_macros.h"
28#include "../../types.h"
29
30struct NonMovable {
31 NonMovable(NonMovable&&) = delete;
32};
33
34struct MovableNonTrivial {
35 int i;
36 constexpr MovableNonTrivial(int ii) : i(ii) {}
37 constexpr MovableNonTrivial(MovableNonTrivial&& o) : i(o.i) { o.i = 0; }
38 friend constexpr bool operator==(const MovableNonTrivial&, const MovableNonTrivial&) = default;
39};
40
41struct MoveMayThrow {
42 MoveMayThrow(MoveMayThrow&&) {}
43};
44
45// Test Constraints:
46// - is_move_constructible_v<E> is true.
47static_assert(std::is_move_constructible_v<std::expected<void, int>>);
48static_assert(std::is_move_constructible_v<std::expected<void, MovableNonTrivial>>);
49static_assert(!std::is_move_constructible_v<std::expected<void, NonMovable>>);
50
51// Test: This constructor is trivial if is_trivially_move_constructible_v<E> is true.
52static_assert(std::is_trivially_move_constructible_v<std::expected<void, int>>);
53static_assert(!std::is_trivially_move_constructible_v<std::expected<void, MovableNonTrivial>>);
54
55// Test: noexcept(is_nothrow_move_constructible_v<E>)
56static_assert(std::is_nothrow_move_constructible_v<std::expected<int, int>>);
57static_assert(!std::is_nothrow_move_constructible_v<std::expected<MoveMayThrow, int>>);
58static_assert(!std::is_nothrow_move_constructible_v<std::expected<int, MoveMayThrow>>);
59static_assert(!std::is_nothrow_move_constructible_v<std::expected<MoveMayThrow, MoveMayThrow>>);
60
61constexpr bool test() {
62 // move the error non-trivial
63 {
64 std::expected<void, MovableNonTrivial> e1(std::unexpect, 5);
65 auto e2 = std::move(e1);
66 assert(!e2.has_value());
67 assert(e2.error().i == 5);
68 assert(!e1.has_value());
69 assert(e1.error().i == 0);
70 }
71
72 // move the error trivial
73 {
74 std::expected<void, int> e1(std::unexpect, 5);
75 auto e2 = std::move(e1);
76 assert(!e2.has_value());
77 assert(e2.error() == 5);
78 assert(!e1.has_value());
79 }
80
81 // move TailClobbererNonTrivialMove as error
82 {
83 std::expected<void, TailClobbererNonTrivialMove<1>> e1(std::unexpect);
84 auto e2 = std::move(e1);
85 assert(!e2.has_value());
86 assert(!e1.has_value());
87 }
88
89 return true;
90}
91
92void testException() {
93#ifndef TEST_HAS_NO_EXCEPTIONS
94 struct Throwing {
95 Throwing() = default;
96 Throwing(Throwing&&) { throw Except{}; }
97 };
98
99 // throw on moving error
100 {
101 std::expected<void, Throwing> e1(std::unexpect);
102 try {
103 [[maybe_unused]] auto e2 = std::move(e1);
104 assert(false);
105 } catch (Except) {
106 }
107 }
108
109#endif // TEST_HAS_NO_EXCEPTIONS
110}
111
112int main(int, char**) {
113 test();
114 static_assert(test());
115 testException();
116 return 0;
117}
118

source code of libcxx/test/std/utilities/expected/expected.void/ctor/ctor.move.pass.cpp