copy.pass.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622
  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. #ifndef TEST_HAS_NO_EXCEPTIONS
  95. struct CopyThrows {
  96. CopyThrows() = default;
  97. CopyThrows(const CopyThrows &) { throw 42; }
  98. CopyThrows &operator=(const CopyThrows &) { throw 42; }
  99. };
  100. struct CopyCannotThrow {
  101. static int alive;
  102. CopyCannotThrow() { ++alive; }
  103. CopyCannotThrow(const CopyCannotThrow &) noexcept { ++alive; }
  104. CopyCannotThrow(CopyCannotThrow &&) noexcept { assert(false); }
  105. CopyCannotThrow &operator=(const CopyCannotThrow &) noexcept = default;
  106. CopyCannotThrow &operator=(CopyCannotThrow &&) noexcept { assert(false); return *this; }
  107. };
  108. int CopyCannotThrow::alive = 0;
  109. struct MoveThrows {
  110. static int alive;
  111. MoveThrows() { ++alive; }
  112. MoveThrows(const MoveThrows &) { ++alive; }
  113. MoveThrows(MoveThrows &&) { throw 42; }
  114. MoveThrows &operator=(const MoveThrows &) { return *this; }
  115. MoveThrows &operator=(MoveThrows &&) { throw 42; }
  116. ~MoveThrows() { --alive; }
  117. };
  118. int MoveThrows::alive = 0;
  119. struct NTCopyAssign {
  120. constexpr NTCopyAssign(int v) : value(v) {}
  121. NTCopyAssign(const NTCopyAssign &) = default;
  122. NTCopyAssign(NTCopyAssign &&) = default;
  123. NTCopyAssign &operator=(const NTCopyAssign &that) {
  124. value = that.value;
  125. return *this;
  126. };
  127. NTCopyAssign &operator=(NTCopyAssign &&) = delete;
  128. int value;
  129. };
  130. static_assert(!std::is_trivially_copy_assignable<NTCopyAssign>::value, "");
  131. static_assert(std::is_copy_assignable<NTCopyAssign>::value, "");
  132. struct TCopyAssign {
  133. constexpr TCopyAssign(int v) : value(v) {}
  134. TCopyAssign(const TCopyAssign &) = default;
  135. TCopyAssign(TCopyAssign &&) = default;
  136. TCopyAssign &operator=(const TCopyAssign &) = default;
  137. TCopyAssign &operator=(TCopyAssign &&) = delete;
  138. int value;
  139. };
  140. static_assert(std::is_trivially_copy_assignable<TCopyAssign>::value, "");
  141. struct TCopyAssignNTMoveAssign {
  142. constexpr TCopyAssignNTMoveAssign(int v) : value(v) {}
  143. TCopyAssignNTMoveAssign(const TCopyAssignNTMoveAssign &) = default;
  144. TCopyAssignNTMoveAssign(TCopyAssignNTMoveAssign &&) = default;
  145. TCopyAssignNTMoveAssign &operator=(const TCopyAssignNTMoveAssign &) = default;
  146. TCopyAssignNTMoveAssign &operator=(TCopyAssignNTMoveAssign &&that) {
  147. value = that.value;
  148. that.value = -1;
  149. return *this;
  150. }
  151. int value;
  152. };
  153. static_assert(std::is_trivially_copy_assignable_v<TCopyAssignNTMoveAssign>, "");
  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. #ifdef _LIBCPP_VERSION // LWG2904
  196. // variant only provides copy assignment when both the copy and move
  197. // constructors are well formed
  198. static_assert(!std::is_copy_assignable<V>::value, "");
  199. #else // _LIBCPP_VERSION // LWG2904
  200. static_assert(std::is_copy_assignable<V>::value, "");
  201. #endif // _LIBCPP_VERSION // LWG2904
  202. }
  203. {
  204. using V = std::variant<int, NoCopy>;
  205. static_assert(!std::is_copy_assignable<V>::value, "");
  206. }
  207. {
  208. using V = std::variant<int, MoveOnly>;
  209. static_assert(!std::is_copy_assignable<V>::value, "");
  210. }
  211. {
  212. using V = std::variant<int, MoveOnlyNT>;
  213. static_assert(!std::is_copy_assignable<V>::value, "");
  214. }
  215. // The following tests are for not-yet-standardized behavior (P0602):
  216. {
  217. using V = std::variant<int, long>;
  218. static_assert(std::is_trivially_copy_assignable<V>::value, "");
  219. }
  220. {
  221. using V = std::variant<int, NTCopyAssign>;
  222. static_assert(!std::is_trivially_copy_assignable<V>::value, "");
  223. static_assert(std::is_copy_assignable<V>::value, "");
  224. }
  225. {
  226. using V = std::variant<int, TCopyAssign>;
  227. static_assert(std::is_trivially_copy_assignable<V>::value, "");
  228. }
  229. {
  230. using V = std::variant<int, TCopyAssignNTMoveAssign>;
  231. static_assert(std::is_trivially_copy_assignable<V>::value, "");
  232. }
  233. #ifndef _LIBCPP_VERSION // LWG2904
  234. {
  235. using V = std::variant<int, CopyOnly>;
  236. static_assert(std::is_trivially_copy_assignable<V>::value, "");
  237. }
  238. #endif // _LIBCPP_VERSION
  239. }
  240. void test_copy_assignment_empty_empty() {
  241. #ifndef TEST_HAS_NO_EXCEPTIONS
  242. using MET = MakeEmptyT;
  243. {
  244. using V = std::variant<int, long, MET>;
  245. V v1(std::in_place_index<0>);
  246. makeEmpty(v1);
  247. V v2(std::in_place_index<0>);
  248. makeEmpty(v2);
  249. V &vref = (v1 = v2);
  250. assert(&vref == &v1);
  251. assert(v1.valueless_by_exception());
  252. assert(v1.index() == std::variant_npos);
  253. }
  254. #endif // TEST_HAS_NO_EXCEPTIONS
  255. }
  256. void test_copy_assignment_non_empty_empty() {
  257. #ifndef TEST_HAS_NO_EXCEPTIONS
  258. using MET = MakeEmptyT;
  259. {
  260. using V = std::variant<int, MET>;
  261. V v1(std::in_place_index<0>, 42);
  262. V v2(std::in_place_index<0>);
  263. makeEmpty(v2);
  264. V &vref = (v1 = v2);
  265. assert(&vref == &v1);
  266. assert(v1.valueless_by_exception());
  267. assert(v1.index() == std::variant_npos);
  268. }
  269. {
  270. using V = std::variant<int, MET, std::string>;
  271. V v1(std::in_place_index<2>, "hello");
  272. V v2(std::in_place_index<0>);
  273. makeEmpty(v2);
  274. V &vref = (v1 = v2);
  275. assert(&vref == &v1);
  276. assert(v1.valueless_by_exception());
  277. assert(v1.index() == std::variant_npos);
  278. }
  279. #endif // TEST_HAS_NO_EXCEPTIONS
  280. }
  281. void test_copy_assignment_empty_non_empty() {
  282. #ifndef TEST_HAS_NO_EXCEPTIONS
  283. using MET = MakeEmptyT;
  284. {
  285. using V = std::variant<int, MET>;
  286. V v1(std::in_place_index<0>);
  287. makeEmpty(v1);
  288. V v2(std::in_place_index<0>, 42);
  289. V &vref = (v1 = v2);
  290. assert(&vref == &v1);
  291. assert(v1.index() == 0);
  292. assert(std::get<0>(v1) == 42);
  293. }
  294. {
  295. using V = std::variant<int, MET, std::string>;
  296. V v1(std::in_place_index<0>);
  297. makeEmpty(v1);
  298. V v2(std::in_place_type<std::string>, "hello");
  299. V &vref = (v1 = v2);
  300. assert(&vref == &v1);
  301. assert(v1.index() == 2);
  302. assert(std::get<2>(v1) == "hello");
  303. }
  304. #endif // TEST_HAS_NO_EXCEPTIONS
  305. }
  306. template <typename T> struct Result { size_t index; T value; };
  307. void test_copy_assignment_same_index() {
  308. {
  309. using V = std::variant<int>;
  310. V v1(43);
  311. V v2(42);
  312. V &vref = (v1 = v2);
  313. assert(&vref == &v1);
  314. assert(v1.index() == 0);
  315. assert(std::get<0>(v1) == 42);
  316. }
  317. {
  318. using V = std::variant<int, long, unsigned>;
  319. V v1(43l);
  320. V v2(42l);
  321. V &vref = (v1 = v2);
  322. assert(&vref == &v1);
  323. assert(v1.index() == 1);
  324. assert(std::get<1>(v1) == 42);
  325. }
  326. {
  327. using V = std::variant<int, CopyAssign, unsigned>;
  328. V v1(std::in_place_type<CopyAssign>, 43);
  329. V v2(std::in_place_type<CopyAssign>, 42);
  330. CopyAssign::reset();
  331. V &vref = (v1 = v2);
  332. assert(&vref == &v1);
  333. assert(v1.index() == 1);
  334. assert(std::get<1>(v1).value == 42);
  335. assert(CopyAssign::copy_construct == 0);
  336. assert(CopyAssign::move_construct == 0);
  337. assert(CopyAssign::copy_assign == 1);
  338. }
  339. #ifndef TEST_HAS_NO_EXCEPTIONS
  340. using MET = MakeEmptyT;
  341. {
  342. using V = std::variant<int, MET, std::string>;
  343. V v1(std::in_place_type<MET>);
  344. MET &mref = std::get<1>(v1);
  345. V v2(std::in_place_type<MET>);
  346. try {
  347. v1 = v2;
  348. assert(false);
  349. } catch (...) {
  350. }
  351. assert(v1.index() == 1);
  352. assert(&std::get<1>(v1) == &mref);
  353. }
  354. #endif // TEST_HAS_NO_EXCEPTIONS
  355. // The following tests are for not-yet-standardized behavior (P0602):
  356. {
  357. struct {
  358. constexpr Result<int> operator()() const {
  359. using V = std::variant<int>;
  360. V v(43);
  361. V v2(42);
  362. v = v2;
  363. return {v.index(), std::get<0>(v)};
  364. }
  365. } test;
  366. constexpr auto result = test();
  367. static_assert(result.index == 0, "");
  368. static_assert(result.value == 42, "");
  369. }
  370. {
  371. struct {
  372. constexpr Result<long> operator()() const {
  373. using V = std::variant<int, long, unsigned>;
  374. V v(43l);
  375. V v2(42l);
  376. v = v2;
  377. return {v.index(), std::get<1>(v)};
  378. }
  379. } test;
  380. constexpr auto result = test();
  381. static_assert(result.index == 1, "");
  382. static_assert(result.value == 42l, "");
  383. }
  384. {
  385. struct {
  386. constexpr Result<int> operator()() const {
  387. using V = std::variant<int, TCopyAssign, unsigned>;
  388. V v(std::in_place_type<TCopyAssign>, 43);
  389. V v2(std::in_place_type<TCopyAssign>, 42);
  390. v = v2;
  391. return {v.index(), std::get<1>(v).value};
  392. }
  393. } test;
  394. constexpr auto result = test();
  395. static_assert(result.index == 1, "");
  396. static_assert(result.value == 42, "");
  397. }
  398. {
  399. struct {
  400. constexpr Result<int> operator()() const {
  401. using V = std::variant<int, TCopyAssignNTMoveAssign, unsigned>;
  402. V v(std::in_place_type<TCopyAssignNTMoveAssign>, 43);
  403. V v2(std::in_place_type<TCopyAssignNTMoveAssign>, 42);
  404. v = v2;
  405. return {v.index(), std::get<1>(v).value};
  406. }
  407. } test;
  408. constexpr auto result = test();
  409. static_assert(result.index == 1, "");
  410. static_assert(result.value == 42, "");
  411. }
  412. }
  413. void test_copy_assignment_different_index() {
  414. {
  415. using V = std::variant<int, long, unsigned>;
  416. V v1(43);
  417. V v2(42l);
  418. V &vref = (v1 = v2);
  419. assert(&vref == &v1);
  420. assert(v1.index() == 1);
  421. assert(std::get<1>(v1) == 42);
  422. }
  423. {
  424. using V = std::variant<int, CopyAssign, unsigned>;
  425. CopyAssign::reset();
  426. V v1(std::in_place_type<unsigned>, 43);
  427. V v2(std::in_place_type<CopyAssign>, 42);
  428. assert(CopyAssign::copy_construct == 0);
  429. assert(CopyAssign::move_construct == 0);
  430. assert(CopyAssign::alive == 1);
  431. V &vref = (v1 = v2);
  432. assert(&vref == &v1);
  433. assert(v1.index() == 1);
  434. assert(std::get<1>(v1).value == 42);
  435. assert(CopyAssign::alive == 2);
  436. assert(CopyAssign::copy_construct == 1);
  437. assert(CopyAssign::move_construct == 1);
  438. assert(CopyAssign::copy_assign == 0);
  439. }
  440. #ifndef TEST_HAS_NO_EXCEPTIONS
  441. {
  442. using V = std::variant<int, CopyThrows, std::string>;
  443. V v1(std::in_place_type<std::string>, "hello");
  444. V v2(std::in_place_type<CopyThrows>);
  445. try {
  446. v1 = v2;
  447. assert(false);
  448. } catch (...) { /* ... */
  449. }
  450. #ifdef _LIBCPP_VERSION // LWG2904
  451. // Test that if copy construction throws then original value is unchanged.
  452. assert(v1.index() == 2);
  453. assert(std::get<2>(v1) == "hello");
  454. #else // _LIBCPP_VERSION // LWG2904
  455. // Test that copy construction is used directly if move construction may throw,
  456. // resulting in a valueless variant if copy throws.
  457. assert(v1.valueless_by_exception());
  458. #endif // _LIBCPP_VERSION // LWG2904
  459. }
  460. {
  461. using V = std::variant<int, MoveThrows, std::string>;
  462. V v1(std::in_place_type<std::string>, "hello");
  463. V v2(std::in_place_type<MoveThrows>);
  464. assert(MoveThrows::alive == 1);
  465. #ifdef _LIBCPP_VERSION // LWG2904
  466. // Test that if move construction throws then the variant is left
  467. // valueless by exception.
  468. try {
  469. v1 = v2;
  470. assert(false);
  471. } catch (...) { /* ... */
  472. }
  473. assert(v1.valueless_by_exception());
  474. assert(v2.index() == 1);
  475. assert(MoveThrows::alive == 1);
  476. #else // _LIBCPP_VERSION // LWG2904
  477. // Test that copy construction is used directly if move construction may throw.
  478. v1 = v2;
  479. assert(v1.index() == 1);
  480. assert(v2.index() == 1);
  481. assert(MoveThrows::alive == 2);
  482. #endif // _LIBCPP_VERSION // LWG2904
  483. }
  484. #ifndef _LIBCPP_VERSION // LWG2904
  485. {
  486. // Test that direct copy construction is preferred when it cannot throw.
  487. using V = std::variant<int, CopyCannotThrow, std::string>;
  488. V v1(std::in_place_type<std::string>, "hello");
  489. V v2(std::in_place_type<CopyCannotThrow>);
  490. assert(CopyCannotThrow::alive == 1);
  491. v1 = v2;
  492. assert(v1.index() == 1);
  493. assert(v2.index() == 1);
  494. assert(CopyCannotThrow::alive == 2);
  495. }
  496. #endif // _LIBCPP_VERSION // LWG2904
  497. {
  498. using V = std::variant<int, CopyThrows, std::string>;
  499. V v1(std::in_place_type<CopyThrows>);
  500. V v2(std::in_place_type<std::string>, "hello");
  501. V &vref = (v1 = v2);
  502. assert(&vref == &v1);
  503. assert(v1.index() == 2);
  504. assert(std::get<2>(v1) == "hello");
  505. assert(v2.index() == 2);
  506. assert(std::get<2>(v2) == "hello");
  507. }
  508. {
  509. using V = std::variant<int, MoveThrows, std::string>;
  510. V v1(std::in_place_type<MoveThrows>);
  511. V v2(std::in_place_type<std::string>, "hello");
  512. V &vref = (v1 = v2);
  513. assert(&vref == &v1);
  514. assert(v1.index() == 2);
  515. assert(std::get<2>(v1) == "hello");
  516. assert(v2.index() == 2);
  517. assert(std::get<2>(v2) == "hello");
  518. }
  519. #endif // TEST_HAS_NO_EXCEPTIONS
  520. // The following tests are for not-yet-standardized behavior (P0602):
  521. {
  522. struct {
  523. constexpr Result<long> operator()() const {
  524. using V = std::variant<int, long, unsigned>;
  525. V v(43);
  526. V v2(42l);
  527. v = v2;
  528. return {v.index(), std::get<1>(v)};
  529. }
  530. } test;
  531. constexpr auto result = test();
  532. static_assert(result.index == 1, "");
  533. static_assert(result.value == 42l, "");
  534. }
  535. {
  536. struct {
  537. constexpr Result<int> operator()() const {
  538. using V = std::variant<int, TCopyAssign, unsigned>;
  539. V v(std::in_place_type<unsigned>, 43);
  540. V v2(std::in_place_type<TCopyAssign>, 42);
  541. v = v2;
  542. return {v.index(), std::get<1>(v).value};
  543. }
  544. } test;
  545. constexpr auto result = test();
  546. static_assert(result.index == 1, "");
  547. static_assert(result.value == 42, "");
  548. }
  549. }
  550. template <size_t NewIdx, class ValueType>
  551. constexpr bool test_constexpr_assign_extension_imp(
  552. std::variant<long, void*, int>&& v, ValueType&& new_value)
  553. {
  554. const std::variant<long, void*, int> cp(
  555. std::forward<ValueType>(new_value));
  556. v = cp;
  557. return v.index() == NewIdx &&
  558. std::get<NewIdx>(v) == std::get<NewIdx>(cp);
  559. }
  560. void test_constexpr_copy_assignment_extension() {
  561. // The following tests are for not-yet-standardized behavior (P0602):
  562. using V = std::variant<long, void*, int>;
  563. static_assert(std::is_trivially_copyable<V>::value, "");
  564. static_assert(std::is_trivially_copy_assignable<V>::value, "");
  565. static_assert(test_constexpr_assign_extension_imp<0>(V(42l), 101l), "");
  566. static_assert(test_constexpr_assign_extension_imp<0>(V(nullptr), 101l), "");
  567. static_assert(test_constexpr_assign_extension_imp<1>(V(42l), nullptr), "");
  568. static_assert(test_constexpr_assign_extension_imp<2>(V(42l), 101), "");
  569. }
  570. int main() {
  571. test_copy_assignment_empty_empty();
  572. test_copy_assignment_non_empty_empty();
  573. test_copy_assignment_empty_non_empty();
  574. test_copy_assignment_same_index();
  575. test_copy_assignment_different_index();
  576. test_copy_assignment_sfinae();
  577. test_copy_assignment_not_noexcept();
  578. test_constexpr_copy_assignment_extension();
  579. }