[clang][Sema] Handle undeduced auto types in HeuristicResolver (#124236)
[llvm-project.git] / libcxx / test / std / utilities / variant / variant.variant / variant.ctor / copy.pass.cpp
blob820ff9e0d1a9d0af618e9cab548014cd18bb05e9
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 //===----------------------------------------------------------------------===//
9 // UNSUPPORTED: c++03, c++11, c++14
11 // <variant>
13 // template <class ...Types> class variant;
15 // constexpr variant(variant const&);
17 #include <cassert>
18 #include <type_traits>
19 #include <variant>
21 #include "test_macros.h"
22 #include "test_workarounds.h"
24 struct NonT {
25 constexpr NonT(int v) : value(v) {}
26 constexpr NonT(const NonT& o) : value(o.value) {}
27 int value;
29 static_assert(!std::is_trivially_copy_constructible<NonT>::value, "");
31 struct NoCopy {
32 NoCopy(const NoCopy&) = delete;
35 struct MoveOnly {
36 MoveOnly(const MoveOnly&) = delete;
37 MoveOnly(MoveOnly&&) = default;
40 struct MoveOnlyNT {
41 MoveOnlyNT(const MoveOnlyNT&) = delete;
42 MoveOnlyNT(MoveOnlyNT&&) {}
45 struct NTCopy {
46 constexpr NTCopy(int v) : value(v) {}
47 NTCopy(const NTCopy& that) : value(that.value) {}
48 NTCopy(NTCopy&&) = delete;
49 int value;
52 static_assert(!std::is_trivially_copy_constructible<NTCopy>::value, "");
53 static_assert(std::is_copy_constructible<NTCopy>::value, "");
55 struct TCopy {
56 constexpr TCopy(int v) : value(v) {}
57 TCopy(TCopy const&) = default;
58 TCopy(TCopy&&) = delete;
59 int value;
62 static_assert(std::is_trivially_copy_constructible<TCopy>::value, "");
64 struct TCopyNTMove {
65 constexpr TCopyNTMove(int v) : value(v) {}
66 TCopyNTMove(const TCopyNTMove&) = default;
67 TCopyNTMove(TCopyNTMove&& that) : value(that.value) { that.value = -1; }
68 int value;
71 static_assert(std::is_trivially_copy_constructible<TCopyNTMove>::value, "");
73 #ifndef TEST_HAS_NO_EXCEPTIONS
74 struct MakeEmptyT {
75 static int alive;
76 MakeEmptyT() { ++alive; }
77 MakeEmptyT(const MakeEmptyT&) {
78 ++alive;
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>);
93 try {
94 v = std::move(v2);
95 assert(false);
96 } catch (...) {
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>;
216 V v1;
217 makeEmpty(v1);
218 const V& cv1 = v1;
219 V v(cv1);
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) {
226 auto v2 = 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 {
251 int i = 0;
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();
274 return true;
277 TEST_CONSTEXPR_CXX20 bool cxx20_constexpr_test() {
278 test_copy_ctor_basic();
279 test_constexpr_copy_ctor_non_trivial();
281 return true;
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());
292 #endif
293 return 0;