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// <variant>
12
13// template <class ...Types> class variant;
14
15// template <class T> constexpr variant(T&&) noexcept(see below);
16
17#include <cassert>
18#include <string>
19#include <type_traits>
20#include <variant>
21#include <memory>
22#include <vector>
23
24#include "test_macros.h"
25#include "variant_test_helpers.h"
26
27struct Dummy {
28 Dummy() = default;
29};
30
31struct ThrowsT {
32 ThrowsT(int) noexcept(false) {}
33};
34
35struct NoThrowT {
36 NoThrowT(int) noexcept(true) {}
37};
38
39struct AnyConstructible {
40 template <typename T>
41 AnyConstructible(T&&) {}
42};
43struct NoConstructible {
44 NoConstructible() = delete;
45};
46template <class T>
47struct RValueConvertibleFrom {
48 RValueConvertibleFrom(T&&) {}
49};
50
51void test_T_ctor_noexcept() {
52 {
53 using V = std::variant<Dummy, NoThrowT>;
54 static_assert(std::is_nothrow_constructible<V, int>::value, "");
55 }
56 {
57 using V = std::variant<Dummy, ThrowsT>;
58 static_assert(!std::is_nothrow_constructible<V, int>::value, "");
59 }
60}
61
62void test_T_ctor_sfinae() {
63 {
64 using V = std::variant<long, long long>;
65 static_assert(!std::is_constructible<V, int>::value, "ambiguous");
66 }
67 {
68 using V = std::variant<std::string, std::string>;
69 static_assert(!std::is_constructible<V, const char*>::value, "ambiguous");
70 }
71 {
72 using V = std::variant<std::string, void*>;
73 static_assert(!std::is_constructible<V, int>::value, "no matching constructor");
74 }
75 {
76 using V = std::variant<std::string, float>;
77 static_assert(!std::is_constructible<V, int>::value, "no matching constructor");
78 }
79 {
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");
82 struct X {
83 operator void*();
84 };
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");
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, "regression on user-defined conversions in constructor");
95 }
96 {
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");
100 }
101}
102
103void test_T_ctor_basic() {
104 {
105 constexpr std::variant<int> v(42);
106 static_assert(v.index() == 0, "");
107 static_assert(std::get<0>(v: v) == 42, "");
108 }
109 {
110 constexpr std::variant<int, long> v(42l);
111 static_assert(v.index() == 1, "");
112 static_assert(std::get<1>(v: v) == 42, "");
113 }
114 {
115 constexpr std::variant<unsigned, long> v(42);
116 static_assert(v.index() == 1, "");
117 static_assert(std::get<1>(v: v) == 42, "");
118 }
119 {
120 std::variant<std::string, bool const> v = "foo";
121 assert(v.index() == 0);
122 assert(std::get<0>(v) == "foo");
123 }
124 {
125 std::variant<bool, std::unique_ptr<int>> v = nullptr;
126 assert(v.index() == 1);
127 assert(std::get<1>(v) == nullptr);
128 }
129 {
130 std::variant<bool const, int> v = true;
131 assert(v.index() == 0);
132 assert(std::get<0>(v));
133 }
134 {
135 std::variant<RValueConvertibleFrom<int>> v1 = 42;
136 assert(v1.index() == 0);
137
138 int x = 42;
139 std::variant<RValueConvertibleFrom<int>, AnyConstructible> v2 = x;
140 assert(v2.index() == 1);
141 }
142}
143
144struct BoomOnAnything {
145 template <class T>
146 constexpr BoomOnAnything(T) {
147 static_assert(!std::is_same<T, T>::value, "");
148 }
149};
150
151void test_no_narrowing_check_for_class_types() {
152 using V = std::variant<int, BoomOnAnything>;
153 V v(42);
154 assert(v.index() == 0);
155 assert(std::get<0>(v) == 42);
156}
157
158struct Bar {};
159struct Baz {};
160void 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, "");
167}
168
169void 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);
174}
175
176int main(int, char**) {
177 test_T_ctor_basic();
178 test_T_ctor_noexcept();
179 test_T_ctor_sfinae();
180 test_no_narrowing_check_for_class_types();
181 test_construction_with_repeated_types();
182 test_vector_bool();
183 return 0;
184}
185

source code of libcxx/test/std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp