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 <size_t I, class ...Args>
18 // variant_alternative_t<I, variant<Types...>>& emplace(Args&&... args);
22 #include <type_traits>
25 #include "archetypes.h"
26 #include "test_convertible.h"
27 #include "test_macros.h"
28 #include "variant_test_helpers.h"
30 template <class Var
, std::size_t I
, class... Args
>
31 constexpr auto test_emplace_exists_imp(int) -> decltype(
32 std::declval
<Var
>().template emplace
<I
>(std::declval
<Args
>()...), true) {
36 template <class, std::size_t, class...>
37 constexpr auto test_emplace_exists_imp(long) -> bool {
41 template <class Var
, std::size_t I
, class... Args
> constexpr bool emplace_exists() {
42 return test_emplace_exists_imp
<Var
, I
, Args
...>(0);
45 void test_emplace_sfinae() {
47 using V
= std::variant
<int, void *, const void *, TestTypes::NoCtors
>;
48 static_assert(emplace_exists
<V
, 0>(), "");
49 static_assert(emplace_exists
<V
, 0, int>(), "");
50 static_assert(!emplace_exists
<V
, 0, decltype(nullptr)>(),
52 static_assert(emplace_exists
<V
, 1, decltype(nullptr)>(), "");
53 static_assert(emplace_exists
<V
, 1, int *>(), "");
54 static_assert(!emplace_exists
<V
, 1, const int *>(), "");
55 static_assert(!emplace_exists
<V
, 1, int>(), "cannot construct");
56 static_assert(emplace_exists
<V
, 2, const int *>(), "");
57 static_assert(emplace_exists
<V
, 2, int *>(), "");
58 static_assert(!emplace_exists
<V
, 3>(), "cannot construct");
60 #if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
62 using V
= std::variant
<int, int &, const int &, int &&, TestTypes::NoCtors
>;
63 static_assert(emplace_exists
<V
, 0>(), "");
64 static_assert(emplace_exists
<V
, 0, int>(), "");
65 static_assert(emplace_exists
<V
, 0, long long>(), "");
66 static_assert(!emplace_exists
<V
, 0, int, int>(), "too many args");
67 static_assert(emplace_exists
<V
, 1, int &>(), "");
68 static_assert(!emplace_exists
<V
, 1>(), "cannot default construct ref");
69 static_assert(!emplace_exists
<V
, 1, const int &>(), "cannot bind ref");
70 static_assert(!emplace_exists
<V
, 1, int &&>(), "cannot bind ref");
71 static_assert(emplace_exists
<V
, 2, int &>(), "");
72 static_assert(emplace_exists
<V
, 2, const int &>(), "");
73 static_assert(emplace_exists
<V
, 2, int &&>(), "");
74 static_assert(!emplace_exists
<V
, 2, void *>(),
75 "not constructible from void*");
76 static_assert(emplace_exists
<V
, 3, int>(), "");
77 static_assert(!emplace_exists
<V
, 3, int &>(), "cannot bind ref");
78 static_assert(!emplace_exists
<V
, 3, const int &>(), "cannot bind ref");
79 static_assert(!emplace_exists
<V
, 3, const int &&>(), "cannot bind ref");
80 static_assert(!emplace_exists
<V
, 4>(), "no ctors");
87 using V
= std::variant
<int>;
89 auto& ref1
= v
.emplace
<0>();
90 static_assert(std::is_same_v
<int&, decltype(ref1
)>, "");
91 assert(std::get
<0>(v
) == 0);
92 assert(&ref1
== &std::get
<0>(v
));
93 auto& ref2
= v
.emplace
<0>(42);
94 static_assert(std::is_same_v
<int&, decltype(ref2
)>, "");
95 assert(std::get
<0>(v
) == 42);
96 assert(&ref2
== &std::get
<0>(v
));
100 std::variant
<int, long, const void *, TestTypes::NoCtors
, std::string
>;
102 V
v(std::in_place_index
<0>, -1);
103 // default emplace a value
104 auto& ref1
= v
.emplace
<1>();
105 static_assert(std::is_same_v
<long&, decltype(ref1
)>, "");
106 assert(std::get
<1>(v
) == 0);
107 assert(&ref1
== &std::get
<1>(v
));
108 auto& ref2
= v
.emplace
<2>(&x
);
109 static_assert(std::is_same_v
<const void*&, decltype(ref2
)>, "");
110 assert(std::get
<2>(v
) == &x
);
111 assert(&ref2
== &std::get
<2>(v
));
112 // emplace with multiple args
113 auto& ref3
= v
.emplace
<4>(3u, 'a');
114 static_assert(std::is_same_v
<std::string
&, decltype(ref3
)>, "");
115 assert(std::get
<4>(v
) == "aaa");
116 assert(&ref3
== &std::get
<4>(v
));
118 #if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
120 using V
= std::variant
<int, long, const int &, int &&, TestTypes::NoCtors
,
125 V
v(std::in_place_index
<0>, -1);
126 // default emplace a value
127 auto& ref1
= v
.emplace
<1>();
128 static_assert(std::is_same_v
<long&, decltype(ref1
)>, "");
129 assert(std::get
<1>(v
) == 0);
130 assert(&ref1
== &std::get
<1>(v
));
131 // emplace a reference
132 auto& ref2
= v
.emplace
<2>(x
);
133 static_assert(std::is_same_v
<&, decltype(ref
)>, "");
134 assert(&std::get
<2>(v
) == &x
);
135 assert(&ref2
== &std::get
<2>(v
));
136 // emplace an rvalue reference
137 auto& ref3
= v
.emplace
<3>(std::move(y
));
138 static_assert(std::is_same_v
<&, decltype(ref
)>, "");
139 assert(&std::get
<3>(v
) == &y
);
140 assert(&ref3
== &std::get
<3>(v
));
141 // re-emplace a new reference over the active member
142 auto& ref4
= v
.emplace
<3>(std::move(z
));
143 static_assert(std::is_same_v
<&, decltype(ref
)>, "");
144 assert(&std::get
<3>(v
) == &z
);
145 assert(&ref4
== &std::get
<3>(v
));
146 // emplace with multiple args
147 auto& ref5
= v
.emplace
<5>(3u, 'a');
148 static_assert(std::is_same_v
<std::string
&, decltype(ref5
)>, "");
149 assert(std::get
<5>(v
) == "aaa");
150 assert(&ref5
== &std::get
<5>(v
));
155 int main(int, char**) {
157 test_emplace_sfinae();