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 {
NonTNonT26 NonT(int v) : value(v) {}
NonTNonT27 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;
MoveOnlyNTMoveOnlyNT43 MoveOnlyNT(MoveOnlyNT &&) {}
44 };
45
46 #ifndef TEST_HAS_NO_EXCEPTIONS
47 struct MakeEmptyT {
48 static int alive;
MakeEmptyTMakeEmptyT49 MakeEmptyT() { ++alive; }
MakeEmptyTMakeEmptyT50 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 }
MakeEmptyTMakeEmptyT55 MakeEmptyT(MakeEmptyT &&) { throw 42; }
operator =MakeEmptyT56 MakeEmptyT &operator=(const MakeEmptyT &) { throw 42; }
operator =MakeEmptyT57 MakeEmptyT &operator=(MakeEmptyT &&) { throw 42; }
~MakeEmptyTMakeEmptyT58 ~MakeEmptyT() { --alive; }
59 };
60
61 int MakeEmptyT::alive = 0;
62
makeEmpty(Variant & v)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
test_copy_ctor_sfinae()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
test_copy_ctor_basic()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
test_copy_ctor_valueless_by_exception()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>
test_constexpr_copy_ctor_extension_imp(std::variant<long,void *,const int> const & v)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
test_constexpr_copy_ctor_extension()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
main()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 }
160