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-exception
6//
7//===----------------------------------------------------------------------===//
8
9// UNSUPPORTED: c++03, c++11, c++14
10
11// <optional>
12
13// constexpr optional(optional<T>&& rhs);
14
15#include <optional>
16#include <type_traits>
17#include <cassert>
18
19#include "test_macros.h"
20#include "archetypes.h"
21
22using std::optional;
23
24template <class T, class ...InitArgs>
25void test(InitArgs&&... args)
26{
27 const optional<T> orig(std::forward<InitArgs>(args)...);
28 optional<T> rhs(orig);
29 bool rhs_engaged = static_cast<bool>(rhs);
30 optional<T> lhs = std::move(rhs);
31 assert(static_cast<bool>(lhs) == rhs_engaged);
32 if (rhs_engaged)
33 assert(*lhs == *orig);
34}
35
36template <class T, class ...InitArgs>
37constexpr bool constexpr_test(InitArgs&&... args)
38{
39 static_assert( std::is_trivially_copy_constructible_v<T>, ""); // requirement
40 const optional<T> orig(std::forward<InitArgs>(args)...);
41 optional<T> rhs(orig);
42 optional<T> lhs = std::move(rhs);
43 return (lhs.has_value() == orig.has_value()) &&
44 (lhs.has_value() ? *lhs == *orig : true);
45}
46
47void test_throwing_ctor() {
48#ifndef TEST_HAS_NO_EXCEPTIONS
49 struct Z {
50 Z() : count(0) {}
51 Z(Z&& o) : count(o.count + 1)
52 { if (count == 2) throw 6; }
53 int count;
54 };
55 Z z;
56 optional<Z> rhs(std::move(z));
57 try
58 {
59 optional<Z> lhs(std::move(rhs));
60 assert(false);
61 }
62 catch (int i)
63 {
64 assert(i == 6);
65 }
66#endif
67}
68
69
70template <class T, class ...InitArgs>
71void test_ref(InitArgs&&... args)
72{
73 optional<T> rhs(std::forward<InitArgs>(args)...);
74 bool rhs_engaged = static_cast<bool>(rhs);
75 optional<T> lhs = std::move(rhs);
76 assert(static_cast<bool>(lhs) == rhs_engaged);
77 if (rhs_engaged)
78 assert(&(*lhs) == &(*rhs));
79}
80
81void test_reference_extension()
82{
83#if defined(_LIBCPP_VERSION) && 0 // FIXME these extensions are currently disabled.
84 using T = TestTypes::TestType;
85 T::reset();
86 {
87 T t;
88 T::reset_constructors();
89 test_ref<T&>();
90 test_ref<T&>(t);
91 assert(T::alive == 1);
92 assert(T::constructed == 0);
93 assert(T::assigned == 0);
94 assert(T::destroyed == 0);
95 }
96 assert(T::destroyed == 1);
97 assert(T::alive == 0);
98 {
99 T t;
100 const T& ct = t;
101 T::reset_constructors();
102 test_ref<T const&>();
103 test_ref<T const&>(t);
104 test_ref<T const&>(ct);
105 assert(T::alive == 1);
106 assert(T::constructed == 0);
107 assert(T::assigned == 0);
108 assert(T::destroyed == 0);
109 }
110 assert(T::alive == 0);
111 assert(T::destroyed == 1);
112 {
113 T t;
114 T::reset_constructors();
115 test_ref<T&&>();
116 test_ref<T&&>(std::move(t));
117 assert(T::alive == 1);
118 assert(T::constructed == 0);
119 assert(T::assigned == 0);
120 assert(T::destroyed == 0);
121 }
122 assert(T::alive == 0);
123 assert(T::destroyed == 1);
124 {
125 T t;
126 const T& ct = t;
127 T::reset_constructors();
128 test_ref<T const&&>();
129 test_ref<T const&&>(std::move(t));
130 test_ref<T const&&>(std::move(ct));
131 assert(T::alive == 1);
132 assert(T::constructed == 0);
133 assert(T::assigned == 0);
134 assert(T::destroyed == 0);
135 }
136 assert(T::alive == 0);
137 assert(T::destroyed == 1);
138 {
139 static_assert(!std::is_copy_constructible<std::optional<T&&>>::value, "");
140 static_assert(!std::is_copy_constructible<std::optional<T const&&>>::value, "");
141 }
142#endif
143}
144
145
146int main(int, char**)
147{
148 test<int>();
149 test<int>(args: 3);
150 static_assert(constexpr_test<int>(), "" );
151 static_assert(constexpr_test<int>(args: 3), "" );
152
153 {
154 optional<const int> o(42);
155 optional<const int> o2(std::move(o));
156 assert(*o2 == 42);
157 }
158 {
159 using T = TestTypes::TestType;
160 T::reset();
161 optional<T> rhs;
162 assert(T::alive == 0);
163 const optional<T> lhs(std::move(rhs));
164 assert(lhs.has_value() == false);
165 assert(rhs.has_value() == false);
166 assert(T::alive == 0);
167 }
168 TestTypes::TestType::reset();
169 {
170 using T = TestTypes::TestType;
171 T::reset();
172 optional<T> rhs(42);
173 assert(T::alive == 1);
174 assert(T::value_constructed == 1);
175 assert(T::move_constructed == 0);
176 const optional<T> lhs(std::move(rhs));
177 assert(lhs.has_value());
178 assert(rhs.has_value());
179 assert(lhs.value().value == 42);
180 assert(rhs.value().value == -1);
181 assert(T::move_constructed == 1);
182 assert(T::alive == 2);
183 }
184 TestTypes::TestType::reset();
185 {
186 using namespace ConstexprTestTypes;
187 test<TestType>();
188 test<TestType>(42);
189 }
190 {
191 using namespace TrivialTestTypes;
192 test<TestType>();
193 test<TestType>(42);
194 }
195 {
196 test_throwing_ctor();
197 }
198 {
199 struct ThrowsMove {
200 ThrowsMove() noexcept(false) {}
201 ThrowsMove(ThrowsMove const&) noexcept(false) {}
202 ThrowsMove(ThrowsMove &&) noexcept(false) {}
203 };
204 static_assert(!std::is_nothrow_move_constructible<optional<ThrowsMove>>::value, "");
205 struct NoThrowMove {
206 NoThrowMove() noexcept(false) {}
207 NoThrowMove(NoThrowMove const&) noexcept(false) {}
208 NoThrowMove(NoThrowMove &&) noexcept(true) {}
209 };
210 static_assert(std::is_nothrow_move_constructible<optional<NoThrowMove>>::value, "");
211 }
212 {
213 test_reference_extension();
214 }
215 {
216 constexpr std::optional<int> o1{4};
217 constexpr std::optional<int> o2 = std::move(o1);
218 static_assert( *o2 == 4, "" );
219 }
220
221 return 0;
222}
223

source code of libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp