copy.pass.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  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 const&);
  14. #include <cassert>
  15. #include <string>
  16. #include <type_traits>
  17. #include <variant>
  18. #include "test_macros.h"
  19. struct NoCopy {
  20. NoCopy(NoCopy const &) = delete;
  21. NoCopy &operator=(NoCopy const &) = default;
  22. };
  23. struct NothrowCopy {
  24. NothrowCopy(NothrowCopy const &) noexcept = default;
  25. NothrowCopy &operator=(NothrowCopy const &) noexcept = default;
  26. };
  27. struct CopyOnly {
  28. CopyOnly(CopyOnly const &) = default;
  29. CopyOnly(CopyOnly &&) = delete;
  30. CopyOnly &operator=(CopyOnly const &) = default;
  31. CopyOnly &operator=(CopyOnly &&) = delete;
  32. };
  33. struct MoveOnly {
  34. MoveOnly(MoveOnly const &) = delete;
  35. MoveOnly(MoveOnly &&) = default;
  36. MoveOnly &operator=(MoveOnly const &) = default;
  37. };
  38. struct MoveOnlyNT {
  39. MoveOnlyNT(MoveOnlyNT const &) = delete;
  40. MoveOnlyNT(MoveOnlyNT &&) {}
  41. MoveOnlyNT &operator=(MoveOnlyNT const &) = default;
  42. };
  43. struct CopyAssign {
  44. static int alive;
  45. static int copy_construct;
  46. static int copy_assign;
  47. static int move_construct;
  48. static int move_assign;
  49. static void reset() {
  50. copy_construct = copy_assign = move_construct = move_assign = alive = 0;
  51. }
  52. CopyAssign(int v) : value(v) { ++alive; }
  53. CopyAssign(CopyAssign const &o) : value(o.value) {
  54. ++alive;
  55. ++copy_construct;
  56. }
  57. CopyAssign(CopyAssign &&o) : value(o.value) {
  58. o.value = -1;
  59. ++alive;
  60. ++move_construct;
  61. }
  62. CopyAssign &operator=(CopyAssign const &o) {
  63. value = o.value;
  64. ++copy_assign;
  65. return *this;
  66. }
  67. CopyAssign &operator=(CopyAssign &&o) {
  68. value = o.value;
  69. o.value = -1;
  70. ++move_assign;
  71. return *this;
  72. }
  73. ~CopyAssign() { --alive; }
  74. int value;
  75. };
  76. int CopyAssign::alive = 0;
  77. int CopyAssign::copy_construct = 0;
  78. int CopyAssign::copy_assign = 0;
  79. int CopyAssign::move_construct = 0;
  80. int CopyAssign::move_assign = 0;
  81. struct CopyMaybeThrows {
  82. CopyMaybeThrows(CopyMaybeThrows const &);
  83. CopyMaybeThrows &operator=(CopyMaybeThrows const &);
  84. };
  85. struct CopyDoesThrow {
  86. CopyDoesThrow(CopyDoesThrow const &) noexcept(false);
  87. CopyDoesThrow &operator=(CopyDoesThrow const &) noexcept(false);
  88. };
  89. #ifndef TEST_HAS_NO_EXCEPTIONS
  90. struct CopyThrows {
  91. CopyThrows() = default;
  92. CopyThrows(CopyThrows const &) { throw 42; }
  93. CopyThrows &operator=(CopyThrows const &) { throw 42; }
  94. };
  95. struct MoveThrows {
  96. static int alive;
  97. MoveThrows() { ++alive; }
  98. MoveThrows(MoveThrows const &) { ++alive; }
  99. MoveThrows(MoveThrows &&) { throw 42; }
  100. MoveThrows &operator=(MoveThrows const &) { return *this; }
  101. MoveThrows &operator=(MoveThrows &&) { throw 42; }
  102. ~MoveThrows() { --alive; }
  103. };
  104. int MoveThrows::alive = 0;
  105. struct MakeEmptyT {
  106. static int alive;
  107. MakeEmptyT() { ++alive; }
  108. MakeEmptyT(MakeEmptyT const &) {
  109. ++alive;
  110. // Don't throw from the copy constructor since variant's assignment
  111. // operator performs a copy before committing to the assignment.
  112. }
  113. MakeEmptyT(MakeEmptyT &&) { throw 42; }
  114. MakeEmptyT &operator=(MakeEmptyT const &) { throw 42; }
  115. MakeEmptyT &operator=(MakeEmptyT &&) { throw 42; }
  116. ~MakeEmptyT() { --alive; }
  117. };
  118. int MakeEmptyT::alive = 0;
  119. template <class Variant> void makeEmpty(Variant &v) {
  120. Variant v2(std::in_place_type<MakeEmptyT>);
  121. try {
  122. v = v2;
  123. assert(false);
  124. } catch (...) {
  125. assert(v.valueless_by_exception());
  126. }
  127. }
  128. #endif // TEST_HAS_NO_EXCEPTIONS
  129. void test_copy_assignment_not_noexcept() {
  130. {
  131. using V = std::variant<CopyMaybeThrows>;
  132. static_assert(!std::is_nothrow_copy_assignable<V>::value, "");
  133. }
  134. {
  135. using V = std::variant<int, CopyDoesThrow>;
  136. static_assert(!std::is_nothrow_copy_assignable<V>::value, "");
  137. }
  138. }
  139. void test_copy_assignment_sfinae() {
  140. {
  141. using V = std::variant<int, long>;
  142. static_assert(std::is_copy_assignable<V>::value, "");
  143. }
  144. {
  145. // variant only provides copy assignment when beth the copy and move
  146. // constructors are well formed
  147. using V = std::variant<int, CopyOnly>;
  148. static_assert(!std::is_copy_assignable<V>::value, "");
  149. }
  150. {
  151. using V = std::variant<int, NoCopy>;
  152. static_assert(!std::is_copy_assignable<V>::value, "");
  153. }
  154. {
  155. using V = std::variant<int, MoveOnly>;
  156. static_assert(!std::is_copy_assignable<V>::value, "");
  157. }
  158. {
  159. using V = std::variant<int, MoveOnlyNT>;
  160. static_assert(!std::is_copy_assignable<V>::value, "");
  161. }
  162. }
  163. void test_copy_assignment_empty_empty() {
  164. #ifndef TEST_HAS_NO_EXCEPTIONS
  165. using MET = MakeEmptyT;
  166. {
  167. using V = std::variant<int, long, MET>;
  168. V v1(std::in_place_index<0>);
  169. makeEmpty(v1);
  170. V v2(std::in_place_index<0>);
  171. makeEmpty(v2);
  172. V &vref = (v1 = v2);
  173. assert(&vref == &v1);
  174. assert(v1.valueless_by_exception());
  175. assert(v1.index() == std::variant_npos);
  176. }
  177. #endif
  178. }
  179. void test_copy_assignment_non_empty_empty() {
  180. #ifndef TEST_HAS_NO_EXCEPTIONS
  181. using MET = MakeEmptyT;
  182. {
  183. using V = std::variant<int, MET>;
  184. V v1(std::in_place_index<0>, 42);
  185. V v2(std::in_place_index<0>);
  186. makeEmpty(v2);
  187. V &vref = (v1 = v2);
  188. assert(&vref == &v1);
  189. assert(v1.valueless_by_exception());
  190. assert(v1.index() == std::variant_npos);
  191. }
  192. {
  193. using V = std::variant<int, MET, std::string>;
  194. V v1(std::in_place_index<2>, "hello");
  195. V v2(std::in_place_index<0>);
  196. makeEmpty(v2);
  197. V &vref = (v1 = v2);
  198. assert(&vref == &v1);
  199. assert(v1.valueless_by_exception());
  200. assert(v1.index() == std::variant_npos);
  201. }
  202. #endif
  203. }
  204. void test_copy_assignment_empty_non_empty() {
  205. #ifndef TEST_HAS_NO_EXCEPTIONS
  206. using MET = MakeEmptyT;
  207. {
  208. using V = std::variant<int, MET>;
  209. V v1(std::in_place_index<0>);
  210. makeEmpty(v1);
  211. V v2(std::in_place_index<0>, 42);
  212. V &vref = (v1 = v2);
  213. assert(&vref == &v1);
  214. assert(v1.index() == 0);
  215. assert(std::get<0>(v1) == 42);
  216. }
  217. {
  218. using V = std::variant<int, MET, std::string>;
  219. V v1(std::in_place_index<0>);
  220. makeEmpty(v1);
  221. V v2(std::in_place_type<std::string>, "hello");
  222. V &vref = (v1 = v2);
  223. assert(&vref == &v1);
  224. assert(v1.index() == 2);
  225. assert(std::get<2>(v1) == "hello");
  226. }
  227. #endif
  228. }
  229. void test_copy_assignment_same_index() {
  230. {
  231. using V = std::variant<int>;
  232. V v1(43);
  233. V v2(42);
  234. V &vref = (v1 = v2);
  235. assert(&vref == &v1);
  236. assert(v1.index() == 0);
  237. assert(std::get<0>(v1) == 42);
  238. }
  239. {
  240. using V = std::variant<int, long, unsigned>;
  241. V v1(43l);
  242. V v2(42l);
  243. V &vref = (v1 = v2);
  244. assert(&vref == &v1);
  245. assert(v1.index() == 1);
  246. assert(std::get<1>(v1) == 42);
  247. }
  248. {
  249. using V = std::variant<int, CopyAssign, unsigned>;
  250. V v1(std::in_place_type<CopyAssign>, 43);
  251. V v2(std::in_place_type<CopyAssign>, 42);
  252. CopyAssign::reset();
  253. V &vref = (v1 = v2);
  254. assert(&vref == &v1);
  255. assert(v1.index() == 1);
  256. assert(std::get<1>(v1).value == 42);
  257. assert(CopyAssign::copy_construct == 0);
  258. assert(CopyAssign::move_construct == 0);
  259. assert(CopyAssign::copy_assign == 1);
  260. }
  261. #ifndef TEST_HAS_NO_EXCEPTIONS
  262. using MET = MakeEmptyT;
  263. {
  264. using V = std::variant<int, MET, std::string>;
  265. V v1(std::in_place_type<MET>);
  266. MET &mref = std::get<1>(v1);
  267. V v2(std::in_place_type<MET>);
  268. try {
  269. v1 = v2;
  270. assert(false);
  271. } catch (...) {
  272. }
  273. assert(v1.index() == 1);
  274. assert(&std::get<1>(v1) == &mref);
  275. }
  276. #endif
  277. }
  278. void test_copy_assignment_different_index() {
  279. {
  280. using V = std::variant<int, long, unsigned>;
  281. V v1(43);
  282. V v2(42l);
  283. V &vref = (v1 = v2);
  284. assert(&vref == &v1);
  285. assert(v1.index() == 1);
  286. assert(std::get<1>(v1) == 42);
  287. }
  288. {
  289. using V = std::variant<int, CopyAssign, unsigned>;
  290. CopyAssign::reset();
  291. V v1(std::in_place_type<unsigned>, 43);
  292. V v2(std::in_place_type<CopyAssign>, 42);
  293. assert(CopyAssign::copy_construct == 0);
  294. assert(CopyAssign::move_construct == 0);
  295. assert(CopyAssign::alive == 1);
  296. V &vref = (v1 = v2);
  297. assert(&vref == &v1);
  298. assert(v1.index() == 1);
  299. assert(std::get<1>(v1).value == 42);
  300. assert(CopyAssign::alive == 2);
  301. assert(CopyAssign::copy_construct == 1);
  302. assert(CopyAssign::move_construct == 1);
  303. assert(CopyAssign::copy_assign == 0);
  304. }
  305. #ifndef TEST_HAS_NO_EXCEPTIONS
  306. {
  307. // Test that if copy construction throws then original value is
  308. // unchanged.
  309. using V = std::variant<int, CopyThrows, std::string>;
  310. V v1(std::in_place_type<std::string>, "hello");
  311. V v2(std::in_place_type<CopyThrows>);
  312. try {
  313. v1 = v2;
  314. assert(false);
  315. } catch (...) { /* ... */
  316. }
  317. assert(v1.index() == 2);
  318. assert(std::get<2>(v1) == "hello");
  319. }
  320. {
  321. // Test that if move construction throws then the variant is left
  322. // valueless by exception.
  323. using V = std::variant<int, MoveThrows, std::string>;
  324. V v1(std::in_place_type<std::string>, "hello");
  325. V v2(std::in_place_type<MoveThrows>);
  326. assert(MoveThrows::alive == 1);
  327. try {
  328. v1 = v2;
  329. assert(false);
  330. } catch (...) { /* ... */
  331. }
  332. assert(v1.valueless_by_exception());
  333. assert(v2.index() == 1);
  334. assert(MoveThrows::alive == 1);
  335. }
  336. {
  337. using V = std::variant<int, CopyThrows, std::string>;
  338. V v1(std::in_place_type<CopyThrows>);
  339. V v2(std::in_place_type<std::string>, "hello");
  340. V &vref = (v1 = v2);
  341. assert(&vref == &v1);
  342. assert(v1.index() == 2);
  343. assert(std::get<2>(v1) == "hello");
  344. assert(v2.index() == 2);
  345. assert(std::get<2>(v2) == "hello");
  346. }
  347. {
  348. using V = std::variant<int, MoveThrows, std::string>;
  349. V v1(std::in_place_type<MoveThrows>);
  350. V v2(std::in_place_type<std::string>, "hello");
  351. V &vref = (v1 = v2);
  352. assert(&vref == &v1);
  353. assert(v1.index() == 2);
  354. assert(std::get<2>(v1) == "hello");
  355. assert(v2.index() == 2);
  356. assert(std::get<2>(v2) == "hello");
  357. }
  358. #endif
  359. }
  360. int main() {
  361. test_copy_assignment_empty_empty();
  362. test_copy_assignment_non_empty_empty();
  363. test_copy_assignment_empty_non_empty();
  364. test_copy_assignment_same_index();
  365. test_copy_assignment_different_index();
  366. test_copy_assignment_sfinae();
  367. test_copy_assignment_not_noexcept();
  368. }