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 // Throwing bad_variant_access is supported starting in macosx10.13
12 // XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11|12}} && !no-exceptions
13
14 // <variant>
15
16 // template <class ...Types> class variant;
17
18 // template <class T> constexpr variant(T&&) noexcept(see below);
19
20 #include <cassert>
21 #include <string>
22 #include <type_traits>
23 #include <variant>
24 #include <memory>
25
26 #include "test_macros.h"
27 #include "variant_test_helpers.h"
28
29 struct Dummy {
30 Dummy() = default;
31 };
32
33 struct ThrowsT {
ThrowsTThrowsT34 ThrowsT(int) noexcept(false) {}
35 };
36
37 struct NoThrowT {
NoThrowTNoThrowT38 NoThrowT(int) noexcept(true) {}
39 };
40
AnyConstructibleAnyConstructible41 struct AnyConstructible { template <typename T> AnyConstructible(T&&) {} };
42 struct NoConstructible { NoConstructible() = delete; };
43 template <class T>
RValueConvertibleFromRValueConvertibleFrom44 struct RValueConvertibleFrom { RValueConvertibleFrom(T&&) {} };
45
test_T_ctor_noexcept()46 void test_T_ctor_noexcept() {
47 {
48 using V = std::variant<Dummy, NoThrowT>;
49 static_assert(std::is_nothrow_constructible<V, int>::value, "");
50 }
51 {
52 using V = std::variant<Dummy, ThrowsT>;
53 static_assert(!std::is_nothrow_constructible<V, int>::value, "");
54 }
55 }
56
test_T_ctor_sfinae()57 void test_T_ctor_sfinae() {
58 {
59 using V = std::variant<long, long long>;
60 static_assert(!std::is_constructible<V, int>::value, "ambiguous");
61 }
62 {
63 using V = std::variant<std::string, std::string>;
64 static_assert(!std::is_constructible<V, const char *>::value, "ambiguous");
65 }
66 {
67 using V = std::variant<std::string, void *>;
68 static_assert(!std::is_constructible<V, int>::value,
69 "no matching constructor");
70 }
71 {
72 using V = std::variant<std::string, float>;
73 static_assert(std::is_constructible<V, int>::value == VariantAllowsNarrowingConversions,
74 "no matching constructor");
75 }
76 {
77 using V = std::variant<std::unique_ptr<int>, bool>;
78 static_assert(!std::is_constructible<V, std::unique_ptr<char>>::value,
79 "no explicit bool in constructor");
80 struct X {
81 operator void*();
82 };
83 static_assert(!std::is_constructible<V, X>::value,
84 "no boolean conversion in constructor");
85 static_assert(!std::is_constructible<V, std::false_type>::value,
86 "no converted to bool in constructor");
87 }
88 {
89 struct X {};
90 struct Y {
91 operator X();
92 };
93 using V = std::variant<X>;
94 static_assert(std::is_constructible<V, Y>::value,
95 "regression on user-defined conversions in constructor");
96 }
97 {
98 using V = std::variant<AnyConstructible, NoConstructible>;
99 static_assert(
100 !std::is_constructible<V, std::in_place_type_t<NoConstructible>>::value,
101 "no matching constructor");
102 static_assert(!std::is_constructible<V, std::in_place_index_t<1>>::value,
103 "no matching constructor");
104 }
105
106
107
108 #if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
109 {
110 using V = std::variant<int, int &&>;
111 static_assert(!std::is_constructible<V, int>::value, "ambiguous");
112 }
113 {
114 using V = std::variant<int, const int &>;
115 static_assert(!std::is_constructible<V, int>::value, "ambiguous");
116 }
117 #endif
118 }
119
test_T_ctor_basic()120 void test_T_ctor_basic() {
121 {
122 constexpr std::variant<int> v(42);
123 static_assert(v.index() == 0, "");
124 static_assert(std::get<0>(v) == 42, "");
125 }
126 {
127 constexpr std::variant<int, long> v(42l);
128 static_assert(v.index() == 1, "");
129 static_assert(std::get<1>(v) == 42, "");
130 }
131 #ifndef TEST_VARIANT_ALLOWS_NARROWING_CONVERSIONS
132 {
133 constexpr std::variant<unsigned, long> v(42);
134 static_assert(v.index() == 1, "");
135 static_assert(std::get<1>(v) == 42, "");
136 }
137 #endif
138 {
139 std::variant<std::string, bool const> v = "foo";
140 assert(v.index() == 0);
141 assert(std::get<0>(v) == "foo");
142 }
143 {
144 std::variant<bool volatile, std::unique_ptr<int>> v = nullptr;
145 assert(v.index() == 1);
146 assert(std::get<1>(v) == nullptr);
147 }
148 {
149 std::variant<bool volatile const, int> v = true;
150 assert(v.index() == 0);
151 assert(std::get<0>(v));
152 }
153 {
154 std::variant<RValueConvertibleFrom<int>> v1 = 42;
155 assert(v1.index() == 0);
156
157 int x = 42;
158 std::variant<RValueConvertibleFrom<int>, AnyConstructible> v2 = x;
159 assert(v2.index() == 1);
160 }
161 #if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
162 {
163 using V = std::variant<const int &, int &&, long>;
164 static_assert(std::is_convertible<int &, V>::value, "must be implicit");
165 int x = 42;
166 V v(x);
167 assert(v.index() == 0);
168 assert(&std::get<0>(v) == &x);
169 }
170 {
171 using V = std::variant<const int &, int &&, long>;
172 static_assert(std::is_convertible<int, V>::value, "must be implicit");
173 int x = 42;
174 V v(std::move(x));
175 assert(v.index() == 1);
176 assert(&std::get<1>(v) == &x);
177 }
178 #endif
179 }
180
181 struct BoomOnAnything {
182 template <class T>
BoomOnAnythingBoomOnAnything183 constexpr BoomOnAnything(T) { static_assert(!std::is_same<T, T>::value, ""); }
184 };
185
test_no_narrowing_check_for_class_types()186 void test_no_narrowing_check_for_class_types() {
187 using V = std::variant<int, BoomOnAnything>;
188 V v(42);
189 assert(v.index() == 0);
190 assert(std::get<0>(v) == 42);
191 }
192
193 struct Bar {};
194 struct Baz {};
test_construction_with_repeated_types()195 void test_construction_with_repeated_types() {
196 using V = std::variant<int, Bar, Baz, int, Baz, int, int>;
197 static_assert(!std::is_constructible<V, int>::value, "");
198 static_assert(!std::is_constructible<V, Baz>::value, "");
199 // OK, the selected type appears only once and so it shouldn't
200 // be affected by the duplicate types.
201 static_assert(std::is_constructible<V, Bar>::value, "");
202 }
203
main(int,char **)204 int main(int, char**) {
205 test_T_ctor_basic();
206 test_T_ctor_noexcept();
207 test_T_ctor_sfinae();
208 test_no_narrowing_check_for_class_types();
209 test_construction_with_repeated_types();
210 return 0;
211 }
212