• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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