1 // -*- C++ -*-
2 //===----------------------------------------------------------------------===//
3 //
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //
8 //===----------------------------------------------------------------------===//
9
10 // UNSUPPORTED: c++03, c++11, c++14
11
12 // Throwing bad_variant_access is supported starting in macosx10.13
13 // XFAIL: with_system_cxx_lib=macosx10.12 && !no-exceptions
14 // XFAIL: with_system_cxx_lib=macosx10.11 && !no-exceptions
15 // XFAIL: with_system_cxx_lib=macosx10.10 && !no-exceptions
16 // XFAIL: with_system_cxx_lib=macosx10.9 && !no-exceptions
17
18 // <variant>
19
20 // template <class ...Types> class variant;
21
22 // template <class T, class ...Args> T& emplace(Args&&... args);
23
24 #include <cassert>
25 #include <string>
26 #include <type_traits>
27 #include <variant>
28
29 #include "archetypes.h"
30 #include "test_convertible.h"
31 #include "test_macros.h"
32 #include "variant_test_helpers.h"
33
34 template <class Var, class T, class... Args>
test_emplace_exists_imp(int)35 constexpr auto test_emplace_exists_imp(int) -> decltype(
36 std::declval<Var>().template emplace<T>(std::declval<Args>()...), true) {
37 return true;
38 }
39
40 template <class, class, class...>
test_emplace_exists_imp(long)41 constexpr auto test_emplace_exists_imp(long) -> bool {
42 return false;
43 }
44
emplace_exists()45 template <class... Args> constexpr bool emplace_exists() {
46 return test_emplace_exists_imp<Args...>(0);
47 }
48
test_emplace_sfinae()49 void test_emplace_sfinae() {
50 {
51 using V = std::variant<int, void *, const void *, TestTypes::NoCtors>;
52 static_assert(emplace_exists<V, int>(), "");
53 static_assert(emplace_exists<V, int, int>(), "");
54 static_assert(!emplace_exists<V, int, decltype(nullptr)>(),
55 "cannot construct");
56 static_assert(emplace_exists<V, void *, decltype(nullptr)>(), "");
57 static_assert(!emplace_exists<V, void *, int>(), "cannot construct");
58 static_assert(emplace_exists<V, void *, int *>(), "");
59 static_assert(!emplace_exists<V, void *, const int *>(), "");
60 static_assert(emplace_exists<V, const void *, const int *>(), "");
61 static_assert(emplace_exists<V, const void *, int *>(), "");
62 static_assert(!emplace_exists<V, TestTypes::NoCtors>(), "cannot construct");
63 }
64 #if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
65 using V = std::variant<int, int &, const int &, int &&, long, long,
66 TestTypes::NoCtors>;
67 static_assert(emplace_exists<V, int>(), "");
68 static_assert(emplace_exists<V, int, int>(), "");
69 static_assert(emplace_exists<V, int, long long>(), "");
70 static_assert(!emplace_exists<V, int, int, int>(), "too many args");
71 static_assert(emplace_exists<V, int &, int &>(), "");
72 static_assert(!emplace_exists<V, int &>(), "cannot default construct ref");
73 static_assert(!emplace_exists<V, int &, const int &>(), "cannot bind ref");
74 static_assert(!emplace_exists<V, int &, int &&>(), "cannot bind ref");
75 static_assert(emplace_exists<V, const int &, int &>(), "");
76 static_assert(emplace_exists<V, const int &, const int &>(), "");
77 static_assert(emplace_exists<V, const int &, int &&>(), "");
78 static_assert(!emplace_exists<V, const int &, void *>(),
79 "not constructible from void*");
80 static_assert(emplace_exists<V, int &&, int>(), "");
81 static_assert(!emplace_exists<V, int &&, int &>(), "cannot bind ref");
82 static_assert(!emplace_exists<V, int &&, const int &>(), "cannot bind ref");
83 static_assert(!emplace_exists<V, int &&, const int &&>(), "cannot bind ref");
84 static_assert(!emplace_exists<V, long, long>(), "ambiguous");
85 static_assert(!emplace_exists<V, TestTypes::NoCtors>(),
86 "cannot construct void");
87 #endif
88 }
89
test_basic()90 void test_basic() {
91 {
92 using V = std::variant<int>;
93 V v(42);
94 auto& ref1 = v.emplace<int>();
95 static_assert(std::is_same_v<int&, decltype(ref1)>, "");
96 assert(std::get<0>(v) == 0);
97 assert(&ref1 == &std::get<0>(v));
98 auto& ref2 = v.emplace<int>(42);
99 static_assert(std::is_same_v<int&, decltype(ref2)>, "");
100 assert(std::get<0>(v) == 42);
101 assert(&ref2 == &std::get<0>(v));
102 }
103 {
104 using V =
105 std::variant<int, long, const void *, TestTypes::NoCtors, std::string>;
106 const int x = 100;
107 V v(std::in_place_type<int>, -1);
108 // default emplace a value
109 auto& ref1 = v.emplace<long>();
110 static_assert(std::is_same_v<long&, decltype(ref1)>, "");
111 assert(std::get<1>(v) == 0);
112 assert(&ref1 == &std::get<1>(v));
113 auto& ref2 = v.emplace<const void *>(&x);
114 static_assert(std::is_same_v<const void *&, decltype(ref2)>, "");
115 assert(std::get<2>(v) == &x);
116 assert(&ref2 == &std::get<2>(v));
117 // emplace with multiple args
118 auto& ref3 = v.emplace<std::string>(3u, 'a');
119 static_assert(std::is_same_v<std::string&, decltype(ref3)>, "");
120 assert(std::get<4>(v) == "aaa");
121 assert(&ref3 == &std::get<4>(v));
122 }
123 #if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
124 {
125 using V = std::variant<int, long, const int &, int &&, TestTypes::NoCtors,
126 std::string>;
127 const int x = 100;
128 int y = 42;
129 int z = 43;
130 V v(std::in_place_index<0>, -1);
131 // default emplace a value
132 auto& ref1 = v.emplace<long>();
133 static_assert(std::is_same_v<long&, decltype(ref1)>, "");
134 assert(std::get<long>(v) == 0);
135 assert(&ref1 == &std::get<long>(v));
136 // emplace a reference
137 auto& ref2 = v.emplace<const int &>(x);
138 static_assert(std::is_same_v<const int&, decltype(ref2)>, "");
139 assert(&std::get<const int &>(v) == &x);
140 assert(&ref2 == &std::get<const int &>(v));
141 // emplace an rvalue reference
142 auto& ref3 = v.emplace<int &&>(std::move(y));
143 static_assert(std::is_same_v<int &&, decltype(ref3)>, "");
144 assert(&std::get<int &&>(v) == &y);
145 assert(&ref3 == &std::get<int &&>(v));
146 // re-emplace a new reference over the active member
147 auto& ref4 = v.emplace<int &&>(std::move(z));
148 static_assert(std::is_same_v<int &, decltype(ref4)>, "");
149 assert(&std::get<int &&>(v) == &z);
150 assert(&ref4 == &std::get<int &&>(v));
151 // emplace with multiple args
152 auto& ref5 = v.emplace<std::string>(3u, 'a');
153 static_assert(std::is_same_v<std::string&, decltype(ref5)>, "");
154 assert(std::get<std::string>(v) == "aaa");
155 assert(&ref5 == &std::get<std::string>(v));
156 }
157 #endif
158 }
159
main(int,char **)160 int main(int, char**) {
161 test_basic();
162 test_emplace_sfinae();
163
164 return 0;
165 }
166