copy.pass.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594
  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. // The following compilers don't generate constexpr special members correctly.
  12. // XFAIL: clang-3.5, clang-3.6, clang-3.7, clang-3.8
  13. // XFAIL: apple-clang-6, apple-clang-7, apple-clang-8.0
  14. // XFAIL: with_system_cxx_lib=macosx10.12
  15. // XFAIL: with_system_cxx_lib=macosx10.11
  16. // XFAIL: with_system_cxx_lib=macosx10.10
  17. // XFAIL: with_system_cxx_lib=macosx10.9
  18. // XFAIL: with_system_cxx_lib=macosx10.7
  19. // XFAIL: with_system_cxx_lib=macosx10.8
  20. // <variant>
  21. // template <class ...Types> class variant;
  22. // variant& operator=(variant const&);
  23. #include <cassert>
  24. #include <string>
  25. #include <type_traits>
  26. #include <variant>
  27. #include "test_macros.h"
  28. struct NoCopy {
  29. NoCopy(const NoCopy &) = delete;
  30. NoCopy &operator=(const NoCopy &) = default;
  31. };
  32. struct CopyOnly {
  33. CopyOnly(const CopyOnly &) = default;
  34. CopyOnly(CopyOnly &&) = delete;
  35. CopyOnly &operator=(const CopyOnly &) = default;
  36. CopyOnly &operator=(CopyOnly &&) = delete;
  37. };
  38. struct MoveOnly {
  39. MoveOnly(const MoveOnly &) = delete;
  40. MoveOnly(MoveOnly &&) = default;
  41. MoveOnly &operator=(const MoveOnly &) = default;
  42. };
  43. struct MoveOnlyNT {
  44. MoveOnlyNT(const MoveOnlyNT &) = delete;
  45. MoveOnlyNT(MoveOnlyNT &&) {}
  46. MoveOnlyNT &operator=(const MoveOnlyNT &) = default;
  47. };
  48. struct CopyAssign {
  49. static int alive;
  50. static int copy_construct;
  51. static int copy_assign;
  52. static int move_construct;
  53. static int move_assign;
  54. static void reset() {
  55. copy_construct = copy_assign = move_construct = move_assign = alive = 0;
  56. }
  57. CopyAssign(int v) : value(v) { ++alive; }
  58. CopyAssign(const CopyAssign &o) : value(o.value) {
  59. ++alive;
  60. ++copy_construct;
  61. }
  62. CopyAssign(CopyAssign &&o) noexcept : value(o.value) {
  63. o.value = -1;
  64. ++alive;
  65. ++move_construct;
  66. }
  67. CopyAssign &operator=(const CopyAssign &o) {
  68. value = o.value;
  69. ++copy_assign;
  70. return *this;
  71. }
  72. CopyAssign &operator=(CopyAssign &&o) noexcept {
  73. value = o.value;
  74. o.value = -1;
  75. ++move_assign;
  76. return *this;
  77. }
  78. ~CopyAssign() { --alive; }
  79. int value;
  80. };
  81. int CopyAssign::alive = 0;
  82. int CopyAssign::copy_construct = 0;
  83. int CopyAssign::copy_assign = 0;
  84. int CopyAssign::move_construct = 0;
  85. int CopyAssign::move_assign = 0;
  86. struct CopyMaybeThrows {
  87. CopyMaybeThrows(const CopyMaybeThrows &);
  88. CopyMaybeThrows &operator=(const CopyMaybeThrows &);
  89. };
  90. struct CopyDoesThrow {
  91. CopyDoesThrow(const CopyDoesThrow &) noexcept(false);
  92. CopyDoesThrow &operator=(const CopyDoesThrow &) noexcept(false);
  93. };
  94. struct NTCopyAssign {
  95. constexpr NTCopyAssign(int v) : value(v) {}
  96. NTCopyAssign(const NTCopyAssign &) = default;
  97. NTCopyAssign(NTCopyAssign &&) = default;
  98. NTCopyAssign &operator=(const NTCopyAssign &that) {
  99. value = that.value;
  100. return *this;
  101. };
  102. NTCopyAssign &operator=(NTCopyAssign &&) = delete;
  103. int value;
  104. };
  105. static_assert(!std::is_trivially_copy_assignable<NTCopyAssign>::value, "");
  106. static_assert(std::is_copy_assignable<NTCopyAssign>::value, "");
  107. struct TCopyAssign {
  108. constexpr TCopyAssign(int v) : value(v) {}
  109. TCopyAssign(const TCopyAssign &) = default;
  110. TCopyAssign(TCopyAssign &&) = default;
  111. TCopyAssign &operator=(const TCopyAssign &) = default;
  112. TCopyAssign &operator=(TCopyAssign &&) = delete;
  113. int value;
  114. };
  115. static_assert(std::is_trivially_copy_assignable<TCopyAssign>::value, "");
  116. struct TCopyAssignNTMoveAssign {
  117. constexpr TCopyAssignNTMoveAssign(int v) : value(v) {}
  118. TCopyAssignNTMoveAssign(const TCopyAssignNTMoveAssign &) = default;
  119. TCopyAssignNTMoveAssign(TCopyAssignNTMoveAssign &&) = default;
  120. TCopyAssignNTMoveAssign &operator=(const TCopyAssignNTMoveAssign &) = default;
  121. TCopyAssignNTMoveAssign &operator=(TCopyAssignNTMoveAssign &&that) {
  122. value = that.value;
  123. that.value = -1;
  124. return *this;
  125. }
  126. int value;
  127. };
  128. static_assert(std::is_trivially_copy_assignable_v<TCopyAssignNTMoveAssign>, "");
  129. #ifndef TEST_HAS_NO_EXCEPTIONS
  130. struct CopyThrows {
  131. CopyThrows() = default;
  132. CopyThrows(const CopyThrows &) { throw 42; }
  133. CopyThrows &operator=(const CopyThrows &) { throw 42; }
  134. };
  135. struct CopyCannotThrow {
  136. static int alive;
  137. CopyCannotThrow() { ++alive; }
  138. CopyCannotThrow(const CopyCannotThrow &) noexcept { ++alive; }
  139. CopyCannotThrow(CopyCannotThrow &&) noexcept { assert(false); }
  140. CopyCannotThrow &operator=(const CopyCannotThrow &) noexcept = default;
  141. CopyCannotThrow &operator=(CopyCannotThrow &&) noexcept { assert(false); return *this; }
  142. };
  143. int CopyCannotThrow::alive = 0;
  144. struct MoveThrows {
  145. static int alive;
  146. MoveThrows() { ++alive; }
  147. MoveThrows(const MoveThrows &) { ++alive; }
  148. MoveThrows(MoveThrows &&) { throw 42; }
  149. MoveThrows &operator=(const MoveThrows &) { return *this; }
  150. MoveThrows &operator=(MoveThrows &&) { throw 42; }
  151. ~MoveThrows() { --alive; }
  152. };
  153. int MoveThrows::alive = 0;
  154. struct MakeEmptyT {
  155. static int alive;
  156. MakeEmptyT() { ++alive; }
  157. MakeEmptyT(const MakeEmptyT &) {
  158. ++alive;
  159. // Don't throw from the copy constructor since variant's assignment
  160. // operator performs a copy before committing to the assignment.
  161. }
  162. MakeEmptyT(MakeEmptyT &&) { throw 42; }
  163. MakeEmptyT &operator=(const MakeEmptyT &) { throw 42; }
  164. MakeEmptyT &operator=(MakeEmptyT &&) { throw 42; }
  165. ~MakeEmptyT() { --alive; }
  166. };
  167. int MakeEmptyT::alive = 0;
  168. template <class Variant> void makeEmpty(Variant &v) {
  169. Variant v2(std::in_place_type<MakeEmptyT>);
  170. try {
  171. v = std::move(v2);
  172. assert(false);
  173. } catch (...) {
  174. assert(v.valueless_by_exception());
  175. }
  176. }
  177. #endif // TEST_HAS_NO_EXCEPTIONS
  178. void test_copy_assignment_not_noexcept() {
  179. {
  180. using V = std::variant<CopyMaybeThrows>;
  181. static_assert(!std::is_nothrow_copy_assignable<V>::value, "");
  182. }
  183. {
  184. using V = std::variant<int, CopyDoesThrow>;
  185. static_assert(!std::is_nothrow_copy_assignable<V>::value, "");
  186. }
  187. }
  188. void test_copy_assignment_sfinae() {
  189. {
  190. using V = std::variant<int, long>;
  191. static_assert(std::is_copy_assignable<V>::value, "");
  192. }
  193. {
  194. using V = std::variant<int, CopyOnly>;
  195. static_assert(std::is_copy_assignable<V>::value, "");
  196. }
  197. {
  198. using V = std::variant<int, NoCopy>;
  199. static_assert(!std::is_copy_assignable<V>::value, "");
  200. }
  201. {
  202. using V = std::variant<int, MoveOnly>;
  203. static_assert(!std::is_copy_assignable<V>::value, "");
  204. }
  205. {
  206. using V = std::variant<int, MoveOnlyNT>;
  207. static_assert(!std::is_copy_assignable<V>::value, "");
  208. }
  209. // The following tests are for not-yet-standardized behavior (P0602):
  210. {
  211. using V = std::variant<int, long>;
  212. static_assert(std::is_trivially_copy_assignable<V>::value, "");
  213. }
  214. {
  215. using V = std::variant<int, NTCopyAssign>;
  216. static_assert(!std::is_trivially_copy_assignable<V>::value, "");
  217. static_assert(std::is_copy_assignable<V>::value, "");
  218. }
  219. {
  220. using V = std::variant<int, TCopyAssign>;
  221. static_assert(std::is_trivially_copy_assignable<V>::value, "");
  222. }
  223. {
  224. using V = std::variant<int, TCopyAssignNTMoveAssign>;
  225. static_assert(std::is_trivially_copy_assignable<V>::value, "");
  226. }
  227. {
  228. using V = std::variant<int, CopyOnly>;
  229. static_assert(std::is_trivially_copy_assignable<V>::value, "");
  230. }
  231. }
  232. void test_copy_assignment_empty_empty() {
  233. #ifndef TEST_HAS_NO_EXCEPTIONS
  234. using MET = MakeEmptyT;
  235. {
  236. using V = std::variant<int, long, MET>;
  237. V v1(std::in_place_index<0>);
  238. makeEmpty(v1);
  239. V v2(std::in_place_index<0>);
  240. makeEmpty(v2);
  241. V &vref = (v1 = v2);
  242. assert(&vref == &v1);
  243. assert(v1.valueless_by_exception());
  244. assert(v1.index() == std::variant_npos);
  245. }
  246. #endif // TEST_HAS_NO_EXCEPTIONS
  247. }
  248. void test_copy_assignment_non_empty_empty() {
  249. #ifndef TEST_HAS_NO_EXCEPTIONS
  250. using MET = MakeEmptyT;
  251. {
  252. using V = std::variant<int, MET>;
  253. V v1(std::in_place_index<0>, 42);
  254. V v2(std::in_place_index<0>);
  255. makeEmpty(v2);
  256. V &vref = (v1 = v2);
  257. assert(&vref == &v1);
  258. assert(v1.valueless_by_exception());
  259. assert(v1.index() == std::variant_npos);
  260. }
  261. {
  262. using V = std::variant<int, MET, std::string>;
  263. V v1(std::in_place_index<2>, "hello");
  264. V v2(std::in_place_index<0>);
  265. makeEmpty(v2);
  266. V &vref = (v1 = v2);
  267. assert(&vref == &v1);
  268. assert(v1.valueless_by_exception());
  269. assert(v1.index() == std::variant_npos);
  270. }
  271. #endif // TEST_HAS_NO_EXCEPTIONS
  272. }
  273. void test_copy_assignment_empty_non_empty() {
  274. #ifndef TEST_HAS_NO_EXCEPTIONS
  275. using MET = MakeEmptyT;
  276. {
  277. using V = std::variant<int, MET>;
  278. V v1(std::in_place_index<0>);
  279. makeEmpty(v1);
  280. V v2(std::in_place_index<0>, 42);
  281. V &vref = (v1 = v2);
  282. assert(&vref == &v1);
  283. assert(v1.index() == 0);
  284. assert(std::get<0>(v1) == 42);
  285. }
  286. {
  287. using V = std::variant<int, MET, std::string>;
  288. V v1(std::in_place_index<0>);
  289. makeEmpty(v1);
  290. V v2(std::in_place_type<std::string>, "hello");
  291. V &vref = (v1 = v2);
  292. assert(&vref == &v1);
  293. assert(v1.index() == 2);
  294. assert(std::get<2>(v1) == "hello");
  295. }
  296. #endif // TEST_HAS_NO_EXCEPTIONS
  297. }
  298. template <typename T> struct Result { size_t index; T value; };
  299. void test_copy_assignment_same_index() {
  300. {
  301. using V = std::variant<int>;
  302. V v1(43);
  303. V v2(42);
  304. V &vref = (v1 = v2);
  305. assert(&vref == &v1);
  306. assert(v1.index() == 0);
  307. assert(std::get<0>(v1) == 42);
  308. }
  309. {
  310. using V = std::variant<int, long, unsigned>;
  311. V v1(43l);
  312. V v2(42l);
  313. V &vref = (v1 = v2);
  314. assert(&vref == &v1);
  315. assert(v1.index() == 1);
  316. assert(std::get<1>(v1) == 42);
  317. }
  318. {
  319. using V = std::variant<int, CopyAssign, unsigned>;
  320. V v1(std::in_place_type<CopyAssign>, 43);
  321. V v2(std::in_place_type<CopyAssign>, 42);
  322. CopyAssign::reset();
  323. V &vref = (v1 = v2);
  324. assert(&vref == &v1);
  325. assert(v1.index() == 1);
  326. assert(std::get<1>(v1).value == 42);
  327. assert(CopyAssign::copy_construct == 0);
  328. assert(CopyAssign::move_construct == 0);
  329. assert(CopyAssign::copy_assign == 1);
  330. }
  331. #ifndef TEST_HAS_NO_EXCEPTIONS
  332. using MET = MakeEmptyT;
  333. {
  334. using V = std::variant<int, MET, std::string>;
  335. V v1(std::in_place_type<MET>);
  336. MET &mref = std::get<1>(v1);
  337. V v2(std::in_place_type<MET>);
  338. try {
  339. v1 = v2;
  340. assert(false);
  341. } catch (...) {
  342. }
  343. assert(v1.index() == 1);
  344. assert(&std::get<1>(v1) == &mref);
  345. }
  346. #endif // TEST_HAS_NO_EXCEPTIONS
  347. // The following tests are for not-yet-standardized behavior (P0602):
  348. {
  349. struct {
  350. constexpr Result<int> operator()() const {
  351. using V = std::variant<int>;
  352. V v(43);
  353. V v2(42);
  354. v = v2;
  355. return {v.index(), std::get<0>(v)};
  356. }
  357. } test;
  358. constexpr auto result = test();
  359. static_assert(result.index == 0, "");
  360. static_assert(result.value == 42, "");
  361. }
  362. {
  363. struct {
  364. constexpr Result<long> operator()() const {
  365. using V = std::variant<int, long, unsigned>;
  366. V v(43l);
  367. V v2(42l);
  368. v = v2;
  369. return {v.index(), std::get<1>(v)};
  370. }
  371. } test;
  372. constexpr auto result = test();
  373. static_assert(result.index == 1, "");
  374. static_assert(result.value == 42l, "");
  375. }
  376. {
  377. struct {
  378. constexpr Result<int> operator()() const {
  379. using V = std::variant<int, TCopyAssign, unsigned>;
  380. V v(std::in_place_type<TCopyAssign>, 43);
  381. V v2(std::in_place_type<TCopyAssign>, 42);
  382. v = v2;
  383. return {v.index(), std::get<1>(v).value};
  384. }
  385. } test;
  386. constexpr auto result = test();
  387. static_assert(result.index == 1, "");
  388. static_assert(result.value == 42, "");
  389. }
  390. {
  391. struct {
  392. constexpr Result<int> operator()() const {
  393. using V = std::variant<int, TCopyAssignNTMoveAssign, unsigned>;
  394. V v(std::in_place_type<TCopyAssignNTMoveAssign>, 43);
  395. V v2(std::in_place_type<TCopyAssignNTMoveAssign>, 42);
  396. v = v2;
  397. return {v.index(), std::get<1>(v).value};
  398. }
  399. } test;
  400. constexpr auto result = test();
  401. static_assert(result.index == 1, "");
  402. static_assert(result.value == 42, "");
  403. }
  404. }
  405. void test_copy_assignment_different_index() {
  406. {
  407. using V = std::variant<int, long, unsigned>;
  408. V v1(43);
  409. V v2(42l);
  410. V &vref = (v1 = v2);
  411. assert(&vref == &v1);
  412. assert(v1.index() == 1);
  413. assert(std::get<1>(v1) == 42);
  414. }
  415. {
  416. using V = std::variant<int, CopyAssign, unsigned>;
  417. CopyAssign::reset();
  418. V v1(std::in_place_type<unsigned>, 43);
  419. V v2(std::in_place_type<CopyAssign>, 42);
  420. assert(CopyAssign::copy_construct == 0);
  421. assert(CopyAssign::move_construct == 0);
  422. assert(CopyAssign::alive == 1);
  423. V &vref = (v1 = v2);
  424. assert(&vref == &v1);
  425. assert(v1.index() == 1);
  426. assert(std::get<1>(v1).value == 42);
  427. assert(CopyAssign::alive == 2);
  428. assert(CopyAssign::copy_construct == 1);
  429. assert(CopyAssign::move_construct == 1);
  430. assert(CopyAssign::copy_assign == 0);
  431. }
  432. #ifndef TEST_HAS_NO_EXCEPTIONS
  433. {
  434. using V = std::variant<int, CopyThrows, std::string>;
  435. V v1(std::in_place_type<std::string>, "hello");
  436. V v2(std::in_place_type<CopyThrows>);
  437. try {
  438. v1 = v2;
  439. assert(false);
  440. } catch (...) { /* ... */
  441. }
  442. // Test that copy construction is used directly if move construction may throw,
  443. // resulting in a valueless variant if copy throws.
  444. assert(v1.valueless_by_exception());
  445. }
  446. {
  447. using V = std::variant<int, MoveThrows, std::string>;
  448. V v1(std::in_place_type<std::string>, "hello");
  449. V v2(std::in_place_type<MoveThrows>);
  450. assert(MoveThrows::alive == 1);
  451. // Test that copy construction is used directly if move construction may throw.
  452. v1 = v2;
  453. assert(v1.index() == 1);
  454. assert(v2.index() == 1);
  455. assert(MoveThrows::alive == 2);
  456. }
  457. {
  458. // Test that direct copy construction is preferred when it cannot throw.
  459. using V = std::variant<int, CopyCannotThrow, std::string>;
  460. V v1(std::in_place_type<std::string>, "hello");
  461. V v2(std::in_place_type<CopyCannotThrow>);
  462. assert(CopyCannotThrow::alive == 1);
  463. v1 = v2;
  464. assert(v1.index() == 1);
  465. assert(v2.index() == 1);
  466. assert(CopyCannotThrow::alive == 2);
  467. }
  468. {
  469. using V = std::variant<int, CopyThrows, std::string>;
  470. V v1(std::in_place_type<CopyThrows>);
  471. V v2(std::in_place_type<std::string>, "hello");
  472. V &vref = (v1 = v2);
  473. assert(&vref == &v1);
  474. assert(v1.index() == 2);
  475. assert(std::get<2>(v1) == "hello");
  476. assert(v2.index() == 2);
  477. assert(std::get<2>(v2) == "hello");
  478. }
  479. {
  480. using V = std::variant<int, MoveThrows, std::string>;
  481. V v1(std::in_place_type<MoveThrows>);
  482. V v2(std::in_place_type<std::string>, "hello");
  483. V &vref = (v1 = v2);
  484. assert(&vref == &v1);
  485. assert(v1.index() == 2);
  486. assert(std::get<2>(v1) == "hello");
  487. assert(v2.index() == 2);
  488. assert(std::get<2>(v2) == "hello");
  489. }
  490. #endif // TEST_HAS_NO_EXCEPTIONS
  491. // The following tests are for not-yet-standardized behavior (P0602):
  492. {
  493. struct {
  494. constexpr Result<long> operator()() const {
  495. using V = std::variant<int, long, unsigned>;
  496. V v(43);
  497. V v2(42l);
  498. v = v2;
  499. return {v.index(), std::get<1>(v)};
  500. }
  501. } test;
  502. constexpr auto result = test();
  503. static_assert(result.index == 1, "");
  504. static_assert(result.value == 42l, "");
  505. }
  506. {
  507. struct {
  508. constexpr Result<int> operator()() const {
  509. using V = std::variant<int, TCopyAssign, unsigned>;
  510. V v(std::in_place_type<unsigned>, 43);
  511. V v2(std::in_place_type<TCopyAssign>, 42);
  512. v = v2;
  513. return {v.index(), std::get<1>(v).value};
  514. }
  515. } test;
  516. constexpr auto result = test();
  517. static_assert(result.index == 1, "");
  518. static_assert(result.value == 42, "");
  519. }
  520. }
  521. template <size_t NewIdx, class ValueType>
  522. constexpr bool test_constexpr_assign_extension_imp(
  523. std::variant<long, void*, int>&& v, ValueType&& new_value)
  524. {
  525. const std::variant<long, void*, int> cp(
  526. std::forward<ValueType>(new_value));
  527. v = cp;
  528. return v.index() == NewIdx &&
  529. std::get<NewIdx>(v) == std::get<NewIdx>(cp);
  530. }
  531. void test_constexpr_copy_assignment_extension() {
  532. // The following tests are for not-yet-standardized behavior (P0602):
  533. using V = std::variant<long, void*, int>;
  534. static_assert(std::is_trivially_copyable<V>::value, "");
  535. static_assert(std::is_trivially_copy_assignable<V>::value, "");
  536. static_assert(test_constexpr_assign_extension_imp<0>(V(42l), 101l), "");
  537. static_assert(test_constexpr_assign_extension_imp<0>(V(nullptr), 101l), "");
  538. static_assert(test_constexpr_assign_extension_imp<1>(V(42l), nullptr), "");
  539. static_assert(test_constexpr_assign_extension_imp<2>(V(42l), 101), "");
  540. }
  541. int main() {
  542. test_copy_assignment_empty_empty();
  543. test_copy_assignment_non_empty_empty();
  544. test_copy_assignment_empty_non_empty();
  545. test_copy_assignment_same_index();
  546. test_copy_assignment_different_index();
  547. test_copy_assignment_sfinae();
  548. test_copy_assignment_not_noexcept();
  549. test_constexpr_copy_assignment_extension();
  550. }