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