T.pass.cpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  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. assert(v.index() == 0);
  179. assert(std::get<0>(v) == "hello");
  180. }
  181. {
  182. using V = std::variant<ThrowsAssignT, std::string>;
  183. V v(std::in_place_type<std::string>, "hello");
  184. v = 42;
  185. assert(v.index() == 0);
  186. assert(std::get<0>(v).value == 42);
  187. }
  188. #endif // TEST_HAS_NO_EXCEPTIONS
  189. }
  190. void test_T_assignment_performs_assignment() {
  191. using namespace RuntimeHelpers;
  192. #ifndef TEST_HAS_NO_EXCEPTIONS
  193. {
  194. using V = std::variant<ThrowsCtorT>;
  195. V v;
  196. v = 42;
  197. assert(v.index() == 0);
  198. assert(std::get<0>(v).value == 42);
  199. }
  200. {
  201. using V = std::variant<ThrowsCtorT, std::string>;
  202. V v;
  203. v = 42;
  204. assert(v.index() == 0);
  205. assert(std::get<0>(v).value == 42);
  206. }
  207. {
  208. using V = std::variant<ThrowsAssignT>;
  209. V v(100);
  210. try {
  211. v = 42;
  212. assert(false);
  213. } catch (...) { /* ... */
  214. }
  215. assert(v.index() == 0);
  216. assert(std::get<0>(v).value == 100);
  217. }
  218. {
  219. using V = std::variant<std::string, ThrowsAssignT>;
  220. V v(100);
  221. try {
  222. v = 42;
  223. assert(false);
  224. } catch (...) { /* ... */
  225. }
  226. assert(v.index() == 1);
  227. assert(std::get<1>(v).value == 100);
  228. }
  229. #endif // TEST_HAS_NO_EXCEPTIONS
  230. }
  231. int main() {
  232. test_T_assignment_basic();
  233. test_T_assignment_performs_construction();
  234. test_T_assignment_performs_assignment();
  235. test_T_assignment_noexcept();
  236. test_T_assignment_sfinae();
  237. }