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
13 // template <class ...Types> class variant;
15 // template <class T> constexpr variant(T&&) noexcept(see below);
19 #include <type_traits>
24 #include "test_macros.h"
25 #include "variant_test_helpers.h"
32 ThrowsT(int) noexcept(false) {}
36 NoThrowT(int) noexcept(true) {}
39 struct AnyConstructible
{
41 AnyConstructible(T
&&) {}
43 struct NoConstructible
{
44 NoConstructible() = delete;
47 struct RValueConvertibleFrom
{
48 RValueConvertibleFrom(T
&&) {}
51 void test_T_ctor_noexcept() {
53 using V
= std::variant
<Dummy
, NoThrowT
>;
54 static_assert(std::is_nothrow_constructible
<V
, int>::value
, "");
57 using V
= std::variant
<Dummy
, ThrowsT
>;
58 static_assert(!std::is_nothrow_constructible
<V
, int>::value
, "");
62 void test_T_ctor_sfinae() {
64 using V
= std::variant
<long, long long>;
65 static_assert(!std::is_constructible
<V
, int>::value
, "ambiguous");
68 using V
= std::variant
<std::string
, std::string
>;
69 static_assert(!std::is_constructible
<V
, const char*>::value
, "ambiguous");
72 using V
= std::variant
<std::string
, void*>;
73 static_assert(!std::is_constructible
<V
, int>::value
, "no matching constructor");
76 using V
= std::variant
<std::string
, float>;
77 static_assert(!std::is_constructible
<V
, int>::value
, "no matching constructor");
80 using V
= std::variant
<std::unique_ptr
<int>, bool>;
81 static_assert(!std::is_constructible
<V
, std::unique_ptr
<char>>::value
, "no explicit bool in constructor");
85 static_assert(!std::is_constructible
<V
, X
>::value
, "no boolean conversion in constructor");
86 static_assert(std::is_constructible
<V
, std::false_type
>::value
, "converted to bool in constructor");
93 using V
= std::variant
<X
>;
94 static_assert(std::is_constructible
<V
, Y
>::value
, "regression on user-defined conversions in constructor");
97 using V
= std::variant
<AnyConstructible
, NoConstructible
>;
98 static_assert(!std::is_constructible
<V
, std::in_place_type_t
<NoConstructible
>>::value
, "no matching constructor");
99 static_assert(!std::is_constructible
<V
, std::in_place_index_t
<1>>::value
, "no matching constructor");
103 void test_T_ctor_basic() {
105 constexpr std::variant
<int> v(42);
106 static_assert(v
.index() == 0, "");
107 static_assert(std::get
<0>(v
) == 42, "");
110 constexpr std::variant
<int, long> v(42l);
111 static_assert(v
.index() == 1, "");
112 static_assert(std::get
<1>(v
) == 42, "");
115 constexpr std::variant
<unsigned, long> v(42);
116 static_assert(v
.index() == 1, "");
117 static_assert(std::get
<1>(v
) == 42, "");
120 std::variant
<std::string
, bool const> v
= "foo";
121 assert(v
.index() == 0);
122 assert(std::get
<0>(v
) == "foo");
125 std::variant
<bool, std::unique_ptr
<int>> v
= nullptr;
126 assert(v
.index() == 1);
127 assert(std::get
<1>(v
) == nullptr);
130 std::variant
<bool const, int> v
= true;
131 assert(v
.index() == 0);
132 assert(std::get
<0>(v
));
135 std::variant
<RValueConvertibleFrom
<int>> v1
= 42;
136 assert(v1
.index() == 0);
139 std::variant
<RValueConvertibleFrom
<int>, AnyConstructible
> v2
= x
;
140 assert(v2
.index() == 1);
144 struct BoomOnAnything
{
146 constexpr BoomOnAnything(T
) {
147 static_assert(!std::is_same
<T
, T
>::value
, "");
151 void test_no_narrowing_check_for_class_types() {
152 using V
= std::variant
<int, BoomOnAnything
>;
154 assert(v
.index() == 0);
155 assert(std::get
<0>(v
) == 42);
160 void test_construction_with_repeated_types() {
161 using V
= std::variant
<int, Bar
, Baz
, int, Baz
, int, int>;
162 static_assert(!std::is_constructible
<V
, int>::value
, "");
163 static_assert(!std::is_constructible
<V
, Baz
>::value
, "");
164 // OK, the selected type appears only once and so it shouldn't
165 // be affected by the duplicate types.
166 static_assert(std::is_constructible
<V
, Bar
>::value
, "");
169 void test_vector_bool() {
170 std::vector
<bool> vec
= {true};
171 std::variant
<bool, int> v
= vec
[0];
172 assert(v
.index() == 0);
173 assert(std::get
<0>(v
) == true);
176 int main(int, char**) {
178 test_T_ctor_noexcept();
179 test_T_ctor_sfinae();
180 test_no_narrowing_check_for_class_types();
181 test_construction_with_repeated_types();