copy.pass.cpp 17 KB

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