1 //===----------------------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // UNSUPPORTED: c++03, c++11, c++14
13 // template <class ...Types> class variant;
15 // constexpr variant(variant const&);
18 #include <type_traits>
21 #include "test_macros.h"
22 #include "test_workarounds.h"
25 constexpr NonT(int v
) : value(v
) {}
26 constexpr NonT(const NonT
& o
) : value(o
.value
) {}
29 static_assert(!std::is_trivially_copy_constructible
<NonT
>::value
, "");
32 NoCopy(const NoCopy
&) = delete;
36 MoveOnly(const MoveOnly
&) = delete;
37 MoveOnly(MoveOnly
&&) = default;
41 MoveOnlyNT(const MoveOnlyNT
&) = delete;
42 MoveOnlyNT(MoveOnlyNT
&&) {}
46 constexpr NTCopy(int v
) : value(v
) {}
47 NTCopy(const NTCopy
& that
) : value(that
.value
) {}
48 NTCopy(NTCopy
&&) = delete;
52 static_assert(!std::is_trivially_copy_constructible
<NTCopy
>::value
, "");
53 static_assert(std::is_copy_constructible
<NTCopy
>::value
, "");
56 constexpr TCopy(int v
) : value(v
) {}
57 TCopy(TCopy
const&) = default;
58 TCopy(TCopy
&&) = delete;
62 static_assert(std::is_trivially_copy_constructible
<TCopy
>::value
, "");
65 constexpr TCopyNTMove(int v
) : value(v
) {}
66 TCopyNTMove(const TCopyNTMove
&) = default;
67 TCopyNTMove(TCopyNTMove
&& that
) : value(that
.value
) { that
.value
= -1; }
71 static_assert(std::is_trivially_copy_constructible
<TCopyNTMove
>::value
, "");
73 #ifndef TEST_HAS_NO_EXCEPTIONS
76 MakeEmptyT() { ++alive
; }
77 MakeEmptyT(const MakeEmptyT
&) {
79 // Don't throw from the copy constructor since variant's assignment
80 // operator performs a copy before committing to the assignment.
82 MakeEmptyT(MakeEmptyT
&&) { throw 42; }
83 MakeEmptyT
& operator=(const MakeEmptyT
&) { throw 42; }
84 MakeEmptyT
& operator=(MakeEmptyT
&&) { throw 42; }
85 ~MakeEmptyT() { --alive
; }
88 int MakeEmptyT::alive
= 0;
90 template <class Variant
>
91 void makeEmpty(Variant
& v
) {
92 Variant
v2(std::in_place_type
<MakeEmptyT
>);
97 assert(v
.valueless_by_exception());
100 #endif // TEST_HAS_NO_EXCEPTIONS
102 constexpr void test_copy_ctor_sfinae() {
104 using V
= std::variant
<int, long>;
105 static_assert(std::is_copy_constructible
<V
>::value
, "");
108 using V
= std::variant
<int, NoCopy
>;
109 static_assert(!std::is_copy_constructible
<V
>::value
, "");
112 using V
= std::variant
<int, MoveOnly
>;
113 static_assert(!std::is_copy_constructible
<V
>::value
, "");
116 using V
= std::variant
<int, MoveOnlyNT
>;
117 static_assert(!std::is_copy_constructible
<V
>::value
, "");
120 // Make sure we properly propagate triviality (see P0602R4).
122 using V
= std::variant
<int, long>;
123 static_assert(std::is_trivially_copy_constructible
<V
>::value
, "");
126 using V
= std::variant
<int, NTCopy
>;
127 static_assert(!std::is_trivially_copy_constructible
<V
>::value
, "");
128 static_assert(std::is_copy_constructible
<V
>::value
, "");
131 using V
= std::variant
<int, TCopy
>;
132 static_assert(std::is_trivially_copy_constructible
<V
>::value
, "");
135 using V
= std::variant
<int, TCopyNTMove
>;
136 static_assert(std::is_trivially_copy_constructible
<V
>::value
, "");
140 TEST_CONSTEXPR_CXX20
void test_copy_ctor_basic() {
142 std::variant
<int> v(std::in_place_index
<0>, 42);
143 std::variant
<int> v2
= v
;
144 assert(v2
.index() == 0);
145 assert(std::get
<0>(v2
) == 42);
148 std::variant
<int, long> v(std::in_place_index
<1>, 42);
149 std::variant
<int, long> v2
= v
;
150 assert(v2
.index() == 1);
151 assert(std::get
<1>(v2
) == 42);
154 std::variant
<NonT
> v(std::in_place_index
<0>, 42);
155 assert(v
.index() == 0);
156 std::variant
<NonT
> v2(v
);
157 assert(v2
.index() == 0);
158 assert(std::get
<0>(v2
).value
== 42);
161 std::variant
<int, NonT
> v(std::in_place_index
<1>, 42);
162 assert(v
.index() == 1);
163 std::variant
<int, NonT
> v2(v
);
164 assert(v2
.index() == 1);
165 assert(std::get
<1>(v2
).value
== 42);
168 // Make sure we properly propagate triviality, which implies constexpr-ness (see P0602R4).
170 constexpr std::variant
<int> v(std::in_place_index
<0>, 42);
171 static_assert(v
.index() == 0, "");
172 constexpr std::variant
<int> v2
= v
;
173 static_assert(v2
.index() == 0, "");
174 static_assert(std::get
<0>(v2
) == 42, "");
177 constexpr std::variant
<int, long> v(std::in_place_index
<1>, 42);
178 static_assert(v
.index() == 1, "");
179 constexpr std::variant
<int, long> v2
= v
;
180 static_assert(v2
.index() == 1, "");
181 static_assert(std::get
<1>(v2
) == 42, "");
184 constexpr std::variant
<TCopy
> v(std::in_place_index
<0>, 42);
185 static_assert(v
.index() == 0, "");
186 constexpr std::variant
<TCopy
> v2(v
);
187 static_assert(v2
.index() == 0, "");
188 static_assert(std::get
<0>(v2
).value
== 42, "");
191 constexpr std::variant
<int, TCopy
> v(std::in_place_index
<1>, 42);
192 static_assert(v
.index() == 1, "");
193 constexpr std::variant
<int, TCopy
> v2(v
);
194 static_assert(v2
.index() == 1, "");
195 static_assert(std::get
<1>(v2
).value
== 42, "");
198 constexpr std::variant
<TCopyNTMove
> v(std::in_place_index
<0>, 42);
199 static_assert(v
.index() == 0, "");
200 constexpr std::variant
<TCopyNTMove
> v2(v
);
201 static_assert(v2
.index() == 0, "");
202 static_assert(std::get
<0>(v2
).value
== 42, "");
205 constexpr std::variant
<int, TCopyNTMove
> v(std::in_place_index
<1>, 42);
206 static_assert(v
.index() == 1, "");
207 constexpr std::variant
<int, TCopyNTMove
> v2(v
);
208 static_assert(v2
.index() == 1, "");
209 static_assert(std::get
<1>(v2
).value
== 42, "");
213 void test_copy_ctor_valueless_by_exception() {
214 #ifndef TEST_HAS_NO_EXCEPTIONS
215 using V
= std::variant
<int, MakeEmptyT
>;
220 assert(v
.valueless_by_exception());
221 #endif // TEST_HAS_NO_EXCEPTIONS
224 template <std::size_t Idx
, class T
>
225 constexpr void test_constexpr_copy_ctor_imp(const T
& v
) {
227 assert(v2
.index() == v
.index());
228 assert(v2
.index() == Idx
);
229 assert(std::get
<Idx
>(v2
) == std::get
<Idx
>(v
));
232 constexpr void test_constexpr_copy_ctor_trivial() {
233 // Make sure we properly propagate triviality, which implies constexpr-ness (see P0602R4).
234 using V
= std::variant
<long, void*, const int>;
235 #ifdef TEST_WORKAROUND_MSVC_BROKEN_IS_TRIVIALLY_COPYABLE
236 static_assert(std::is_trivially_destructible
<V
>::value
, "");
237 static_assert(std::is_trivially_copy_constructible
<V
>::value
, "");
238 static_assert(std::is_trivially_move_constructible
<V
>::value
, "");
239 static_assert(!std::is_copy_assignable
<V
>::value
, "");
240 static_assert(!std::is_move_assignable
<V
>::value
, "");
241 #else // TEST_WORKAROUND_MSVC_BROKEN_IS_TRIVIALLY_COPYABLE
242 static_assert(std::is_trivially_copyable
<V
>::value
, "");
243 #endif // TEST_WORKAROUND_MSVC_BROKEN_IS_TRIVIALLY_COPYABLE
244 static_assert(std::is_trivially_copy_constructible
<V
>::value
, "");
245 test_constexpr_copy_ctor_imp
<0>(V(42l));
246 test_constexpr_copy_ctor_imp
<1>(V(nullptr));
247 test_constexpr_copy_ctor_imp
<2>(V(101));
250 struct NonTrivialCopyCtor
{
252 constexpr NonTrivialCopyCtor(int ii
) : i(ii
) {}
253 constexpr NonTrivialCopyCtor(const NonTrivialCopyCtor
& other
) : i(other
.i
) {}
254 constexpr NonTrivialCopyCtor(NonTrivialCopyCtor
&& other
) = default;
255 TEST_CONSTEXPR_CXX20
~NonTrivialCopyCtor() = default;
256 friend constexpr bool operator==(const NonTrivialCopyCtor
& x
, const NonTrivialCopyCtor
& y
) { return x
.i
== y
.i
; }
259 TEST_CONSTEXPR_CXX20
void test_constexpr_copy_ctor_non_trivial() {
260 // Test !is_trivially_move_constructible
261 using V
= std::variant
<long, NonTrivialCopyCtor
, void*>;
262 static_assert(!std::is_trivially_copy_constructible
<V
>::value
, "");
263 test_constexpr_copy_ctor_imp
<0>(V(42l));
264 test_constexpr_copy_ctor_imp
<1>(V(NonTrivialCopyCtor(5)));
265 test_constexpr_copy_ctor_imp
<2>(V(nullptr));
268 void non_constexpr_test() { test_copy_ctor_valueless_by_exception(); }
270 constexpr bool cxx17_constexpr_test() {
271 test_copy_ctor_sfinae();
272 test_constexpr_copy_ctor_trivial();
277 TEST_CONSTEXPR_CXX20
bool cxx20_constexpr_test() {
278 test_copy_ctor_basic();
279 test_constexpr_copy_ctor_non_trivial();
284 int main(int, char**) {
285 non_constexpr_test();
286 cxx17_constexpr_test();
287 cxx20_constexpr_test();
289 static_assert(cxx17_constexpr_test());
290 #if TEST_STD_VER >= 20
291 static_assert(cxx20_constexpr_test());