]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - test/std/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp
Vendor import of libc++ trunk r290819:
[FreeBSD/FreeBSD.git] / test / std / utilities / variant / variant.variant / variant.ctor / copy.pass.cpp
1 // -*- C++ -*-
2 //===----------------------------------------------------------------------===//
3 //
4 //                     The LLVM Compiler Infrastructure
5 //
6 // This file is dual licensed under the MIT and the University of Illinois Open
7 // Source Licenses. See LICENSE.TXT for details.
8 //
9 //===----------------------------------------------------------------------===//
10
11 // UNSUPPORTED: c++98, c++03, c++11, c++14
12
13 // <variant>
14
15 // template <class ...Types> class variant;
16
17 // variant(variant const&);
18
19 #include <cassert>
20 #include <type_traits>
21 #include <variant>
22
23 #include "test_macros.h"
24
25 struct NonT {
26   NonT(int v) : value(v) {}
27   NonT(const NonT &o) : value(o.value) {}
28   int value;
29 };
30 static_assert(!std::is_trivially_copy_constructible<NonT>::value, "");
31
32 struct NoCopy {
33   NoCopy(const NoCopy &) = delete;
34 };
35
36 struct MoveOnly {
37   MoveOnly(const MoveOnly &) = delete;
38   MoveOnly(MoveOnly &&) = default;
39 };
40
41 struct MoveOnlyNT {
42   MoveOnlyNT(const MoveOnlyNT &) = delete;
43   MoveOnlyNT(MoveOnlyNT &&) {}
44 };
45
46 #ifndef TEST_HAS_NO_EXCEPTIONS
47 struct MakeEmptyT {
48   static int alive;
49   MakeEmptyT() { ++alive; }
50   MakeEmptyT(const MakeEmptyT &) {
51     ++alive;
52     // Don't throw from the copy constructor since variant's assignment
53     // operator performs a copy before committing to the assignment.
54   }
55   MakeEmptyT(MakeEmptyT &&) { throw 42; }
56   MakeEmptyT &operator=(const MakeEmptyT &) { throw 42; }
57   MakeEmptyT &operator=(MakeEmptyT &&) { throw 42; }
58   ~MakeEmptyT() { --alive; }
59 };
60
61 int MakeEmptyT::alive = 0;
62
63 template <class Variant> void makeEmpty(Variant &v) {
64   Variant v2(std::in_place_type<MakeEmptyT>);
65   try {
66     v = v2;
67     assert(false);
68   } catch (...) {
69     assert(v.valueless_by_exception());
70   }
71 }
72 #endif // TEST_HAS_NO_EXCEPTIONS
73
74 void test_copy_ctor_sfinae() {
75   {
76     using V = std::variant<int, long>;
77     static_assert(std::is_copy_constructible<V>::value, "");
78   }
79   {
80     using V = std::variant<int, NoCopy>;
81     static_assert(!std::is_copy_constructible<V>::value, "");
82   }
83   {
84     using V = std::variant<int, MoveOnly>;
85     static_assert(!std::is_copy_constructible<V>::value, "");
86   }
87   {
88     using V = std::variant<int, MoveOnlyNT>;
89     static_assert(!std::is_copy_constructible<V>::value, "");
90   }
91 }
92
93 void test_copy_ctor_basic() {
94   {
95     std::variant<int> v(std::in_place_index<0>, 42);
96     std::variant<int> v2 = v;
97     assert(v2.index() == 0);
98     assert(std::get<0>(v2) == 42);
99   }
100   {
101     std::variant<int, long> v(std::in_place_index<1>, 42);
102     std::variant<int, long> v2 = v;
103     assert(v2.index() == 1);
104     assert(std::get<1>(v2) == 42);
105   }
106   {
107     std::variant<NonT> v(std::in_place_index<0>, 42);
108     assert(v.index() == 0);
109     std::variant<NonT> v2(v);
110     assert(v2.index() == 0);
111     assert(std::get<0>(v2).value == 42);
112   }
113   {
114     std::variant<int, NonT> v(std::in_place_index<1>, 42);
115     assert(v.index() == 1);
116     std::variant<int, NonT> v2(v);
117     assert(v2.index() == 1);
118     assert(std::get<1>(v2).value == 42);
119   }
120 }
121
122 void test_copy_ctor_valueless_by_exception() {
123 #ifndef TEST_HAS_NO_EXCEPTIONS
124   using V = std::variant<int, MakeEmptyT>;
125   V v1;
126   makeEmpty(v1);
127   const V &cv1 = v1;
128   V v(cv1);
129   assert(v.valueless_by_exception());
130 #endif
131 }
132
133 template <size_t Idx>
134 constexpr bool test_constexpr_copy_ctor_extension_imp(
135     std::variant<long, void*, const int> const& v)
136 {
137   auto v2 = v;
138   return v2.index() == v.index() &&
139          v2.index() == Idx &&
140         std::get<Idx>(v2) == std::get<Idx>(v);
141 }
142
143 void test_constexpr_copy_ctor_extension() {
144 #ifdef _LIBCPP_VERSION
145   using V = std::variant<long, void*, const int>;
146   static_assert(std::is_trivially_copyable<V>::value, "");
147   static_assert(std::is_trivially_copy_constructible<V>::value, "");
148   static_assert(test_constexpr_copy_ctor_extension_imp<0>(V(42l)), "");
149   static_assert(test_constexpr_copy_ctor_extension_imp<1>(V(nullptr)), "");
150   static_assert(test_constexpr_copy_ctor_extension_imp<2>(V(101)), "");
151 #endif
152 }
153
154 int main() {
155   test_copy_ctor_basic();
156   test_copy_ctor_valueless_by_exception();
157   test_copy_ctor_sfinae();
158   test_constexpr_copy_ctor_extension();
159 }