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