2 //===----------------------------------------------------------------------===//
4 // The LLVM Compiler Infrastructure
6 // This file is dual licensed under the MIT and the University of Illinois Open
7 // Source Licenses. See LICENSE.TXT for details.
9 //===----------------------------------------------------------------------===//
11 // UNSUPPORTED: c++98, c++03, c++11, c++14
13 // XFAIL: with_system_cxx_lib=macosx10.12
14 // XFAIL: with_system_cxx_lib=macosx10.11
15 // XFAIL: with_system_cxx_lib=macosx10.10
16 // XFAIL: with_system_cxx_lib=macosx10.9
17 // XFAIL: with_system_cxx_lib=macosx10.7
18 // XFAIL: with_system_cxx_lib=macosx10.8
22 // template <class ...Types> class variant;
25 // variant& operator=(T&&) noexcept(see below);
29 #include <type_traits>
32 #include "test_macros.h"
33 #include "variant_test_helpers.hpp"
35 namespace MetaHelpers {
42 ThrowsCtorT(int) noexcept(false) {}
43 ThrowsCtorT &operator=(int) noexcept { return *this; }
46 struct ThrowsAssignT {
47 ThrowsAssignT(int) noexcept {}
48 ThrowsAssignT &operator=(int) noexcept(false) { return *this; }
52 NoThrowT(int) noexcept {}
53 NoThrowT &operator=(int) noexcept { return *this; }
56 } // namespace MetaHelpers
58 namespace RuntimeHelpers {
59 #ifndef TEST_HAS_NO_EXCEPTIONS
63 ThrowsCtorT() : value(0) {}
64 ThrowsCtorT(int) noexcept(false) { throw 42; }
65 ThrowsCtorT &operator=(int v) noexcept {
71 struct ThrowsAssignT {
73 ThrowsAssignT() : value(0) {}
74 ThrowsAssignT(int v) noexcept : value(v) {}
75 ThrowsAssignT &operator=(int) noexcept(false) { throw 42; }
80 NoThrowT() : value(0) {}
81 NoThrowT(int v) noexcept : value(v) {}
82 NoThrowT &operator=(int v) noexcept {
88 #endif // !defined(TEST_HAS_NO_EXCEPTIONS)
89 } // namespace RuntimeHelpers
91 void test_T_assignment_noexcept() {
92 using namespace MetaHelpers;
94 using V = std::variant<Dummy, NoThrowT>;
95 static_assert(std::is_nothrow_assignable<V, int>::value, "");
98 using V = std::variant<Dummy, ThrowsCtorT>;
99 static_assert(!std::is_nothrow_assignable<V, int>::value, "");
102 using V = std::variant<Dummy, ThrowsAssignT>;
103 static_assert(!std::is_nothrow_assignable<V, int>::value, "");
107 void test_T_assignment_sfinae() {
109 using V = std::variant<long, unsigned>;
110 static_assert(!std::is_assignable<V, int>::value, "ambiguous");
113 using V = std::variant<std::string, std::string>;
114 static_assert(!std::is_assignable<V, const char *>::value, "ambiguous");
117 using V = std::variant<std::string, void *>;
118 static_assert(!std::is_assignable<V, int>::value, "no matching operator=");
120 #if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
122 using V = std::variant<int, int &&>;
123 static_assert(!std::is_assignable<V, int>::value, "ambiguous");
126 using V = std::variant<int, const int &>;
127 static_assert(!std::is_assignable<V, int>::value, "ambiguous");
132 void test_T_assignment_basic() {
134 std::variant<int> v(43);
136 assert(v.index() == 0);
137 assert(std::get<0>(v) == 42);
140 std::variant<int, long> v(43l);
142 assert(v.index() == 0);
143 assert(std::get<0>(v) == 42);
145 assert(v.index() == 1);
146 assert(std::get<1>(v) == 43);
148 #if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
150 using V = std::variant<int &, int &&, long>;
154 assert(v.index() == 0);
155 assert(&std::get<0>(v) == &x);
157 assert(v.index() == 1);
158 assert(&std::get<1>(v) == &x);
159 // 'long' is selected by FUN(const int &) since 'const int &' cannot bind
163 assert(v.index() == 2);
164 assert(std::get<2>(v) == 42);
169 void test_T_assignment_performs_construction() {
170 using namespace RuntimeHelpers;
171 #ifndef TEST_HAS_NO_EXCEPTIONS
173 using V = std::variant<std::string, ThrowsCtorT>;
174 V v(std::in_place_type<std::string>, "hello");
177 } catch (...) { /* ... */
179 assert(v.valueless_by_exception());
182 using V = std::variant<ThrowsAssignT, std::string>;
183 V v(std::in_place_type<std::string>, "hello");
185 assert(v.index() == 0);
186 assert(std::get<0>(v).value == 42);
191 void test_T_assignment_performs_assignment() {
192 using namespace RuntimeHelpers;
193 #ifndef TEST_HAS_NO_EXCEPTIONS
195 using V = std::variant<ThrowsCtorT>;
198 assert(v.index() == 0);
199 assert(std::get<0>(v).value == 42);
202 using V = std::variant<ThrowsCtorT, std::string>;
205 assert(v.index() == 0);
206 assert(std::get<0>(v).value == 42);
209 using V = std::variant<ThrowsAssignT>;
214 } catch (...) { /* ... */
216 assert(v.index() == 0);
217 assert(std::get<0>(v).value == 100);
220 using V = std::variant<std::string, ThrowsAssignT>;
225 } catch (...) { /* ... */
227 assert(v.index() == 1);
228 assert(std::get<1>(v).value == 100);
234 test_T_assignment_basic();
235 test_T_assignment_performs_construction();
236 test_T_assignment_performs_assignment();
237 test_T_assignment_noexcept();
238 test_T_assignment_sfinae();