move.pass.cpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  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. // <variant>
  12. // template <class ...Types> class variant;
  13. // variant& operator=(variant&&) noexcept(see below);
  14. #include <cassert>
  15. #include <string>
  16. #include <type_traits>
  17. #include <utility>
  18. #include <variant>
  19. #include "test_macros.h"
  20. #include "variant_test_helpers.hpp"
  21. struct NoCopy {
  22. NoCopy(NoCopy const &) = delete;
  23. NoCopy &operator=(NoCopy const &) = default;
  24. };
  25. struct CopyOnly {
  26. CopyOnly(CopyOnly const &) = default;
  27. CopyOnly(CopyOnly &&) = delete;
  28. CopyOnly &operator=(CopyOnly const &) = default;
  29. CopyOnly &operator=(CopyOnly &&) = delete;
  30. };
  31. struct MoveOnly {
  32. MoveOnly(MoveOnly const &) = delete;
  33. MoveOnly(MoveOnly &&) = default;
  34. MoveOnly &operator=(MoveOnly const &) = delete;
  35. MoveOnly &operator=(MoveOnly &&) = default;
  36. };
  37. struct MoveOnlyNT {
  38. MoveOnlyNT(MoveOnlyNT const &) = delete;
  39. MoveOnlyNT(MoveOnlyNT &&) {}
  40. MoveOnlyNT &operator=(MoveOnlyNT const &) = delete;
  41. MoveOnlyNT &operator=(MoveOnlyNT &&) = default;
  42. };
  43. struct MoveOnlyOddNothrow {
  44. MoveOnlyOddNothrow(MoveOnlyOddNothrow &&) noexcept(false) {}
  45. MoveOnlyOddNothrow(MoveOnlyOddNothrow const &) = delete;
  46. MoveOnlyOddNothrow &operator=(MoveOnlyOddNothrow &&) noexcept = default;
  47. MoveOnlyOddNothrow &operator=(MoveOnlyOddNothrow const &) = delete;
  48. };
  49. struct MoveAssignOnly {
  50. MoveAssignOnly(MoveAssignOnly &&) = delete;
  51. MoveAssignOnly &operator=(MoveAssignOnly &&) = default;
  52. };
  53. struct MoveAssign {
  54. static int move_construct;
  55. static int move_assign;
  56. static void reset() { move_construct = move_assign = 0; }
  57. MoveAssign(int v) : value(v) {}
  58. MoveAssign(MoveAssign &&o) : value(o.value) {
  59. ++move_construct;
  60. o.value = -1;
  61. }
  62. MoveAssign &operator=(MoveAssign &&o) {
  63. value = o.value;
  64. ++move_assign;
  65. o.value = -1;
  66. return *this;
  67. }
  68. int value;
  69. };
  70. int MoveAssign::move_construct = 0;
  71. int MoveAssign::move_assign = 0;
  72. void test_move_assignment_noexcept() {
  73. {
  74. using V = std::variant<int>;
  75. static_assert(std::is_nothrow_move_assignable<V>::value, "");
  76. }
  77. {
  78. using V = std::variant<MoveOnly>;
  79. static_assert(std::is_nothrow_move_assignable<V>::value, "");
  80. }
  81. {
  82. using V = std::variant<int, long>;
  83. static_assert(std::is_nothrow_move_assignable<V>::value, "");
  84. }
  85. {
  86. using V = std::variant<int, MoveOnly>;
  87. static_assert(std::is_nothrow_move_assignable<V>::value, "");
  88. }
  89. {
  90. using V = std::variant<MoveOnlyNT>;
  91. static_assert(!std::is_nothrow_move_assignable<V>::value, "");
  92. }
  93. {
  94. using V = std::variant<MoveOnlyOddNothrow>;
  95. static_assert(!std::is_nothrow_move_assignable<V>::value, "");
  96. }
  97. }
  98. void test_move_assignment_sfinae() {
  99. {
  100. using V = std::variant<int, long>;
  101. static_assert(std::is_move_assignable<V>::value, "");
  102. }
  103. {
  104. // variant only provides move assignment when both the move constructor
  105. // and move assignment operator are well formed.
  106. using V = std::variant<int, CopyOnly>;
  107. static_assert(!std::is_move_assignable<V>::value, "");
  108. }
  109. {
  110. using V = std::variant<int, NoCopy>;
  111. static_assert(!std::is_move_assignable<V>::value, "");
  112. }
  113. {
  114. using V = std::variant<int, MoveOnly>;
  115. static_assert(std::is_move_assignable<V>::value, "");
  116. }
  117. {
  118. using V = std::variant<int, MoveOnlyNT>;
  119. static_assert(std::is_move_assignable<V>::value, "");
  120. }
  121. {
  122. // variant only provides move assignment when the types also provide
  123. // a move constructor.
  124. using V = std::variant<int, MoveAssignOnly>;
  125. static_assert(!std::is_move_assignable<V>::value, "");
  126. }
  127. }
  128. void test_move_assignment_empty_empty() {
  129. #ifndef TEST_HAS_NO_EXCEPTIONS
  130. using MET = MakeEmptyT;
  131. {
  132. using V = std::variant<int, long, MET>;
  133. V v1(std::in_place_index<0>);
  134. makeEmpty(v1);
  135. V v2(std::in_place_index<0>);
  136. makeEmpty(v2);
  137. V &vref = (v1 = std::move(v2));
  138. assert(&vref == &v1);
  139. assert(v1.valueless_by_exception());
  140. assert(v1.index() == std::variant_npos);
  141. }
  142. #endif
  143. }
  144. void test_move_assignment_non_empty_empty() {
  145. #ifndef TEST_HAS_NO_EXCEPTIONS
  146. using MET = MakeEmptyT;
  147. {
  148. using V = std::variant<int, MET>;
  149. V v1(std::in_place_index<0>, 42);
  150. V v2(std::in_place_index<0>);
  151. makeEmpty(v2);
  152. V &vref = (v1 = std::move(v2));
  153. assert(&vref == &v1);
  154. assert(v1.valueless_by_exception());
  155. assert(v1.index() == std::variant_npos);
  156. }
  157. {
  158. using V = std::variant<int, MET, std::string>;
  159. V v1(std::in_place_index<2>, "hello");
  160. V v2(std::in_place_index<0>);
  161. makeEmpty(v2);
  162. V &vref = (v1 = std::move(v2));
  163. assert(&vref == &v1);
  164. assert(v1.valueless_by_exception());
  165. assert(v1.index() == std::variant_npos);
  166. }
  167. #endif
  168. }
  169. void test_move_assignment_empty_non_empty() {
  170. #ifndef TEST_HAS_NO_EXCEPTIONS
  171. using MET = MakeEmptyT;
  172. {
  173. using V = std::variant<int, MET>;
  174. V v1(std::in_place_index<0>);
  175. makeEmpty(v1);
  176. V v2(std::in_place_index<0>, 42);
  177. V &vref = (v1 = std::move(v2));
  178. assert(&vref == &v1);
  179. assert(v1.index() == 0);
  180. assert(std::get<0>(v1) == 42);
  181. }
  182. {
  183. using V = std::variant<int, MET, std::string>;
  184. V v1(std::in_place_index<0>);
  185. makeEmpty(v1);
  186. V v2(std::in_place_type<std::string>, "hello");
  187. V &vref = (v1 = std::move(v2));
  188. assert(&vref == &v1);
  189. assert(v1.index() == 2);
  190. assert(std::get<2>(v1) == "hello");
  191. }
  192. #endif
  193. }
  194. void test_move_assignment_same_index() {
  195. {
  196. using V = std::variant<int>;
  197. V v1(43);
  198. V v2(42);
  199. V &vref = (v1 = std::move(v2));
  200. assert(&vref == &v1);
  201. assert(v1.index() == 0);
  202. assert(std::get<0>(v1) == 42);
  203. }
  204. {
  205. using V = std::variant<int, long, unsigned>;
  206. V v1(43l);
  207. V v2(42l);
  208. V &vref = (v1 = std::move(v2));
  209. assert(&vref == &v1);
  210. assert(v1.index() == 1);
  211. assert(std::get<1>(v1) == 42);
  212. }
  213. {
  214. using V = std::variant<int, MoveAssign, unsigned>;
  215. V v1(std::in_place_type<MoveAssign>, 43);
  216. V v2(std::in_place_type<MoveAssign>, 42);
  217. MoveAssign::reset();
  218. V &vref = (v1 = std::move(v2));
  219. assert(&vref == &v1);
  220. assert(v1.index() == 1);
  221. assert(std::get<1>(v1).value == 42);
  222. assert(MoveAssign::move_construct == 0);
  223. assert(MoveAssign::move_assign == 1);
  224. }
  225. #ifndef TEST_HAS_NO_EXCEPTIONS
  226. using MET = MakeEmptyT;
  227. {
  228. using V = std::variant<int, MET, std::string>;
  229. V v1(std::in_place_type<MET>);
  230. MET &mref = std::get<1>(v1);
  231. V v2(std::in_place_type<MET>);
  232. try {
  233. v1 = std::move(v2);
  234. assert(false);
  235. } catch (...) {
  236. }
  237. assert(v1.index() == 1);
  238. assert(&std::get<1>(v1) == &mref);
  239. }
  240. #endif
  241. }
  242. void test_move_assignment_different_index() {
  243. {
  244. using V = std::variant<int, long, unsigned>;
  245. V v1(43);
  246. V v2(42l);
  247. V &vref = (v1 = std::move(v2));
  248. assert(&vref == &v1);
  249. assert(v1.index() == 1);
  250. assert(std::get<1>(v1) == 42);
  251. }
  252. {
  253. using V = std::variant<int, MoveAssign, unsigned>;
  254. V v1(std::in_place_type<unsigned>, 43);
  255. V v2(std::in_place_type<MoveAssign>, 42);
  256. MoveAssign::reset();
  257. V &vref = (v1 = std::move(v2));
  258. assert(&vref == &v1);
  259. assert(v1.index() == 1);
  260. assert(std::get<1>(v1).value == 42);
  261. assert(MoveAssign::move_construct == 1);
  262. assert(MoveAssign::move_assign == 0);
  263. }
  264. #ifndef TEST_HAS_NO_EXCEPTIONS
  265. using MET = MakeEmptyT;
  266. {
  267. using V = std::variant<int, MET, std::string>;
  268. V v1(std::in_place_type<int>);
  269. V v2(std::in_place_type<MET>);
  270. try {
  271. v1 = std::move(v2);
  272. assert(false);
  273. } catch (...) {
  274. }
  275. assert(v1.valueless_by_exception());
  276. assert(v1.index() == std::variant_npos);
  277. }
  278. {
  279. using V = std::variant<int, MET, std::string>;
  280. V v1(std::in_place_type<MET>);
  281. V v2(std::in_place_type<std::string>, "hello");
  282. V &vref = (v1 = std::move(v2));
  283. assert(&vref == &v1);
  284. assert(v1.index() == 2);
  285. assert(std::get<2>(v1) == "hello");
  286. }
  287. #endif
  288. }
  289. int main() {
  290. test_move_assignment_empty_empty();
  291. test_move_assignment_non_empty_empty();
  292. test_move_assignment_empty_non_empty();
  293. test_move_assignment_same_index();
  294. test_move_assignment_different_index();
  295. test_move_assignment_sfinae();
  296. test_move_assignment_noexcept();
  297. }