T.pass.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  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. // UNSUPPORTED: c++98, c++03, c++11, c++14
  11. // XFAIL: with_system_cxx_lib=macosx10.12
  12. // XFAIL: with_system_cxx_lib=macosx10.11
  13. // XFAIL: with_system_cxx_lib=macosx10.10
  14. // XFAIL: with_system_cxx_lib=macosx10.9
  15. // XFAIL: with_system_cxx_lib=macosx10.7
  16. // XFAIL: with_system_cxx_lib=macosx10.8
  17. // <variant>
  18. // template <class ...Types> class variant;
  19. // template <class T>
  20. // variant& operator=(T&&) noexcept(see below);
  21. #include <cassert>
  22. #include <string>
  23. #include <type_traits>
  24. #include <variant>
  25. #include "test_macros.h"
  26. #include "variant_test_helpers.hpp"
  27. namespace MetaHelpers {
  28. struct Dummy {
  29. Dummy() = default;
  30. };
  31. struct ThrowsCtorT {
  32. ThrowsCtorT(int) noexcept(false) {}
  33. ThrowsCtorT &operator=(int) noexcept { return *this; }
  34. };
  35. struct ThrowsAssignT {
  36. ThrowsAssignT(int) noexcept {}
  37. ThrowsAssignT &operator=(int) noexcept(false) { return *this; }
  38. };
  39. struct NoThrowT {
  40. NoThrowT(int) noexcept {}
  41. NoThrowT &operator=(int) noexcept { return *this; }
  42. };
  43. } // namespace MetaHelpers
  44. namespace RuntimeHelpers {
  45. #ifndef TEST_HAS_NO_EXCEPTIONS
  46. struct ThrowsCtorT {
  47. int value;
  48. ThrowsCtorT() : value(0) {}
  49. ThrowsCtorT(int) noexcept(false) { throw 42; }
  50. ThrowsCtorT &operator=(int v) noexcept {
  51. value = v;
  52. return *this;
  53. }
  54. };
  55. struct MoveCrashes {
  56. int value;
  57. MoveCrashes(int v = 0) noexcept : value{v} {}
  58. MoveCrashes(MoveCrashes &&) noexcept { assert(false); }
  59. MoveCrashes &operator=(MoveCrashes &&) noexcept { assert(false); return *this; }
  60. MoveCrashes &operator=(int v) noexcept {
  61. value = v;
  62. return *this;
  63. }
  64. };
  65. struct ThrowsCtorTandMove {
  66. int value;
  67. ThrowsCtorTandMove() : value(0) {}
  68. ThrowsCtorTandMove(int) noexcept(false) { throw 42; }
  69. ThrowsCtorTandMove(ThrowsCtorTandMove &&) noexcept(false) { assert(false); }
  70. ThrowsCtorTandMove &operator=(int v) noexcept {
  71. value = v;
  72. return *this;
  73. }
  74. };
  75. struct ThrowsAssignT {
  76. int value;
  77. ThrowsAssignT() : value(0) {}
  78. ThrowsAssignT(int v) noexcept : value(v) {}
  79. ThrowsAssignT &operator=(int) noexcept(false) { throw 42; }
  80. };
  81. struct NoThrowT {
  82. int value;
  83. NoThrowT() : value(0) {}
  84. NoThrowT(int v) noexcept : value(v) {}
  85. NoThrowT &operator=(int v) noexcept {
  86. value = v;
  87. return *this;
  88. }
  89. };
  90. #endif // !defined(TEST_HAS_NO_EXCEPTIONS)
  91. } // namespace RuntimeHelpers
  92. void test_T_assignment_noexcept() {
  93. using namespace MetaHelpers;
  94. {
  95. using V = std::variant<Dummy, NoThrowT>;
  96. static_assert(std::is_nothrow_assignable<V, int>::value, "");
  97. }
  98. {
  99. using V = std::variant<Dummy, ThrowsCtorT>;
  100. static_assert(!std::is_nothrow_assignable<V, int>::value, "");
  101. }
  102. {
  103. using V = std::variant<Dummy, ThrowsAssignT>;
  104. static_assert(!std::is_nothrow_assignable<V, int>::value, "");
  105. }
  106. }
  107. void test_T_assignment_sfinae() {
  108. {
  109. using V = std::variant<long, unsigned>;
  110. static_assert(!std::is_assignable<V, int>::value, "ambiguous");
  111. }
  112. {
  113. using V = std::variant<std::string, std::string>;
  114. static_assert(!std::is_assignable<V, const char *>::value, "ambiguous");
  115. }
  116. {
  117. using V = std::variant<std::string, void *>;
  118. static_assert(!std::is_assignable<V, int>::value, "no matching operator=");
  119. }
  120. #if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
  121. {
  122. using V = std::variant<int, int &&>;
  123. static_assert(!std::is_assignable<V, int>::value, "ambiguous");
  124. }
  125. {
  126. using V = std::variant<int, const int &>;
  127. static_assert(!std::is_assignable<V, int>::value, "ambiguous");
  128. }
  129. #endif // TEST_VARIANT_HAS_NO_REFERENCES
  130. }
  131. void test_T_assignment_basic() {
  132. {
  133. std::variant<int> v(43);
  134. v = 42;
  135. assert(v.index() == 0);
  136. assert(std::get<0>(v) == 42);
  137. }
  138. {
  139. std::variant<int, long> v(43l);
  140. v = 42;
  141. assert(v.index() == 0);
  142. assert(std::get<0>(v) == 42);
  143. v = 43l;
  144. assert(v.index() == 1);
  145. assert(std::get<1>(v) == 43);
  146. }
  147. #if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
  148. {
  149. using V = std::variant<int &, int &&, long>;
  150. int x = 42;
  151. V v(43l);
  152. v = x;
  153. assert(v.index() == 0);
  154. assert(&std::get<0>(v) == &x);
  155. v = std::move(x);
  156. assert(v.index() == 1);
  157. assert(&std::get<1>(v) == &x);
  158. // 'long' is selected by FUN(const int &) since 'const int &' cannot bind
  159. // to 'int&'.
  160. const int &cx = x;
  161. v = cx;
  162. assert(v.index() == 2);
  163. assert(std::get<2>(v) == 42);
  164. }
  165. #endif // TEST_VARIANT_HAS_NO_REFERENCES
  166. }
  167. void test_T_assignment_performs_construction() {
  168. using namespace RuntimeHelpers;
  169. #ifndef TEST_HAS_NO_EXCEPTIONS
  170. {
  171. using V = std::variant<std::string, ThrowsCtorT>;
  172. V v(std::in_place_type<std::string>, "hello");
  173. try {
  174. v = 42;
  175. assert(false);
  176. } catch (...) { /* ... */
  177. }
  178. #ifdef _LIBCPP_VERSION // LWG2904
  179. assert(v.valueless_by_exception());
  180. #else // _LIBCPP_VERSION
  181. assert(v.index() == 0);
  182. assert(std::get<0>(v) == "hello");
  183. #endif // _LIBCPP_VERSION
  184. }
  185. {
  186. using V = std::variant<ThrowsAssignT, std::string>;
  187. V v(std::in_place_type<std::string>, "hello");
  188. v = 42;
  189. assert(v.index() == 0);
  190. assert(std::get<0>(v).value == 42);
  191. }
  192. #ifdef _LIBCPP_VERSION // LWG2904
  193. {
  194. // Test that nothrow direct construction is preferred to nothrow move.
  195. using V = std::variant<MoveCrashes, std::string>;
  196. V v(std::in_place_type<std::string>, "hello");
  197. v = 42;
  198. assert(v.index() == 0);
  199. assert(std::get<0>(v).value == 42);
  200. }
  201. {
  202. // Test that throwing direct construction is preferred to copy-and-move when
  203. // move can throw.
  204. using V = std::variant<ThrowsCtorTandMove, std::string>;
  205. V v(std::in_place_type<std::string>, "hello");
  206. try {
  207. v = 42;
  208. assert(false);
  209. } catch(...) { /* ... */
  210. }
  211. assert(v.valueless_by_exception());
  212. }
  213. #endif // _LIBCPP_VERSION // LWG2904
  214. #endif // TEST_HAS_NO_EXCEPTIONS
  215. }
  216. void test_T_assignment_performs_assignment() {
  217. using namespace RuntimeHelpers;
  218. #ifndef TEST_HAS_NO_EXCEPTIONS
  219. {
  220. using V = std::variant<ThrowsCtorT>;
  221. V v;
  222. v = 42;
  223. assert(v.index() == 0);
  224. assert(std::get<0>(v).value == 42);
  225. }
  226. {
  227. using V = std::variant<ThrowsCtorT, std::string>;
  228. V v;
  229. v = 42;
  230. assert(v.index() == 0);
  231. assert(std::get<0>(v).value == 42);
  232. }
  233. {
  234. using V = std::variant<ThrowsAssignT>;
  235. V v(100);
  236. try {
  237. v = 42;
  238. assert(false);
  239. } catch (...) { /* ... */
  240. }
  241. assert(v.index() == 0);
  242. assert(std::get<0>(v).value == 100);
  243. }
  244. {
  245. using V = std::variant<std::string, ThrowsAssignT>;
  246. V v(100);
  247. try {
  248. v = 42;
  249. assert(false);
  250. } catch (...) { /* ... */
  251. }
  252. assert(v.index() == 1);
  253. assert(std::get<1>(v).value == 100);
  254. }
  255. #endif // TEST_HAS_NO_EXCEPTIONS
  256. }
  257. int main() {
  258. test_T_assignment_basic();
  259. test_T_assignment_performs_construction();
  260. test_T_assignment_performs_assignment();
  261. test_T_assignment_noexcept();
  262. test_T_assignment_sfinae();
  263. }