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
11 // XFAIL: availability-bad_variant_access-missing && !no-exceptions
15 // template <class ...Types> class variant;
17 // template <class T> constexpr variant(T&&) noexcept(see below);
21 #include <type_traits>
25 #include "test_macros.h"
26 #include "variant_test_helpers.h"
33 ThrowsT(int) noexcept(false) {}
37 NoThrowT(int) noexcept(true) {}
40 struct AnyConstructible
{ template <typename T
> AnyConstructible(T
&&) {} };
41 struct NoConstructible
{ NoConstructible() = delete; };
43 struct RValueConvertibleFrom
{ RValueConvertibleFrom(T
&&) {} };
45 void test_T_ctor_noexcept() {
47 using V
= std::variant
<Dummy
, NoThrowT
>;
48 static_assert(std::is_nothrow_constructible
<V
, int>::value
, "");
51 using V
= std::variant
<Dummy
, ThrowsT
>;
52 static_assert(!std::is_nothrow_constructible
<V
, int>::value
, "");
56 void test_T_ctor_sfinae() {
58 using V
= std::variant
<long, long long>;
59 static_assert(!std::is_constructible
<V
, int>::value
, "ambiguous");
62 using V
= std::variant
<std::string
, std::string
>;
63 static_assert(!std::is_constructible
<V
, const char *>::value
, "ambiguous");
66 using V
= std::variant
<std::string
, void *>;
67 static_assert(!std::is_constructible
<V
, int>::value
,
68 "no matching constructor");
71 using V
= std::variant
<std::string
, float>;
72 static_assert(std::is_constructible
<V
, int>::value
== VariantAllowsNarrowingConversions
,
73 "no matching constructor");
76 using V
= std::variant
<std::unique_ptr
<int>, bool>;
77 static_assert(!std::is_constructible
<V
, std::unique_ptr
<char>>::value
,
78 "no explicit bool in constructor");
82 static_assert(!std::is_constructible
<V
, X
>::value
,
83 "no boolean conversion in constructor");
84 static_assert(!std::is_constructible
<V
, std::false_type
>::value
,
85 "no converted to bool in constructor");
92 using V
= std::variant
<X
>;
93 static_assert(std::is_constructible
<V
, Y
>::value
,
94 "regression on user-defined conversions in constructor");
97 using V
= std::variant
<AnyConstructible
, NoConstructible
>;
99 !std::is_constructible
<V
, std::in_place_type_t
<NoConstructible
>>::value
,
100 "no matching constructor");
101 static_assert(!std::is_constructible
<V
, std::in_place_index_t
<1>>::value
,
102 "no matching constructor");
107 #if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
109 using V
= std::variant
<int, int &&>;
110 static_assert(!std::is_constructible
<V
, int>::value
, "ambiguous");
113 using V
= std::variant
<int, const int &>;
114 static_assert(!std::is_constructible
<V
, int>::value
, "ambiguous");
119 void test_T_ctor_basic() {
121 constexpr std::variant
<int> v(42);
122 static_assert(v
.index() == 0, "");
123 static_assert(std::get
<0>(v
) == 42, "");
126 constexpr std::variant
<int, long> v(42l);
127 static_assert(v
.index() == 1, "");
128 static_assert(std::get
<1>(v
) == 42, "");
130 #ifndef TEST_VARIANT_ALLOWS_NARROWING_CONVERSIONS
132 constexpr std::variant
<unsigned, long> v(42);
133 static_assert(v
.index() == 1, "");
134 static_assert(std::get
<1>(v
) == 42, "");
138 std::variant
<std::string
, bool const> v
= "foo";
139 assert(v
.index() == 0);
140 assert(std::get
<0>(v
) == "foo");
143 std::variant
<bool volatile, std::unique_ptr
<int>> v
= nullptr;
144 assert(v
.index() == 1);
145 assert(std::get
<1>(v
) == nullptr);
148 std::variant
<bool volatile const, int> v
= true;
149 assert(v
.index() == 0);
150 assert(std::get
<0>(v
));
153 std::variant
<RValueConvertibleFrom
<int>> v1
= 42;
154 assert(v1
.index() == 0);
157 std::variant
<RValueConvertibleFrom
<int>, AnyConstructible
> v2
= x
;
158 assert(v2
.index() == 1);
160 #if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
162 using V
= std::variant
<const int &, int &&, long>;
163 static_assert(std::is_convertible
<int &, V
>::value
, "must be implicit");
166 assert(v
.index() == 0);
167 assert(&std::get
<0>(v
) == &x
);
170 using V
= std::variant
<const int &, int &&, long>;
171 static_assert(std::is_convertible
<int, V
>::value
, "must be implicit");
174 assert(v
.index() == 1);
175 assert(&std::get
<1>(v
) == &x
);
180 struct BoomOnAnything
{
182 constexpr BoomOnAnything(T
) { static_assert(!std::is_same
<T
, T
>::value
, ""); }
185 void test_no_narrowing_check_for_class_types() {
186 using V
= std::variant
<int, BoomOnAnything
>;
188 assert(v
.index() == 0);
189 assert(std::get
<0>(v
) == 42);
194 void test_construction_with_repeated_types() {
195 using V
= std::variant
<int, Bar
, Baz
, int, Baz
, int, int>;
196 static_assert(!std::is_constructible
<V
, int>::value
, "");
197 static_assert(!std::is_constructible
<V
, Baz
>::value
, "");
198 // OK, the selected type appears only once and so it shouldn't
199 // be affected by the duplicate types.
200 static_assert(std::is_constructible
<V
, Bar
>::value
, "");
203 int main(int, char**) {
205 test_T_ctor_noexcept();
206 test_T_ctor_sfinae();
207 test_no_narrowing_check_for_class_types();
208 test_construction_with_repeated_types();