move.pass.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. //===----------------------------------------------------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. // <tuple>
  9. // template <class... Types> class tuple;
  10. // tuple& operator=(tuple&& u);
  11. // UNSUPPORTED: c++98, c++03
  12. #include <memory>
  13. #include <tuple>
  14. #include <utility>
  15. #include <cassert>
  16. #include "test_macros.h"
  17. #include "MoveOnly.h"
  18. struct NonAssignable {
  19. NonAssignable& operator=(NonAssignable const&) = delete;
  20. NonAssignable& operator=(NonAssignable&&) = delete;
  21. };
  22. struct CopyAssignable {
  23. CopyAssignable& operator=(CopyAssignable const&) = default;
  24. CopyAssignable& operator=(CopyAssignable&&) = delete;
  25. };
  26. static_assert(std::is_copy_assignable<CopyAssignable>::value, "");
  27. struct MoveAssignable {
  28. MoveAssignable& operator=(MoveAssignable const&) = delete;
  29. MoveAssignable& operator=(MoveAssignable&&) = default;
  30. };
  31. struct CountAssign {
  32. static int copied;
  33. static int moved;
  34. static void reset() { copied = moved = 0; }
  35. CountAssign() = default;
  36. CountAssign& operator=(CountAssign const&) { ++copied; return *this; }
  37. CountAssign& operator=(CountAssign&&) { ++moved; return *this; }
  38. };
  39. int CountAssign::copied = 0;
  40. int CountAssign::moved = 0;
  41. int main(int, char**)
  42. {
  43. {
  44. typedef std::tuple<> T;
  45. T t0;
  46. T t;
  47. t = std::move(t0);
  48. }
  49. {
  50. typedef std::tuple<MoveOnly> T;
  51. T t0(MoveOnly(0));
  52. T t;
  53. t = std::move(t0);
  54. assert(std::get<0>(t) == 0);
  55. }
  56. {
  57. typedef std::tuple<MoveOnly, MoveOnly> T;
  58. T t0(MoveOnly(0), MoveOnly(1));
  59. T t;
  60. t = std::move(t0);
  61. assert(std::get<0>(t) == 0);
  62. assert(std::get<1>(t) == 1);
  63. }
  64. {
  65. typedef std::tuple<MoveOnly, MoveOnly, MoveOnly> T;
  66. T t0(MoveOnly(0), MoveOnly(1), MoveOnly(2));
  67. T t;
  68. t = std::move(t0);
  69. assert(std::get<0>(t) == 0);
  70. assert(std::get<1>(t) == 1);
  71. assert(std::get<2>(t) == 2);
  72. }
  73. {
  74. // test reference assignment.
  75. using T = std::tuple<int&, int&&>;
  76. int x = 42;
  77. int y = 100;
  78. int x2 = -1;
  79. int y2 = 500;
  80. T t(x, std::move(y));
  81. T t2(x2, std::move(y2));
  82. t = std::move(t2);
  83. assert(std::get<0>(t) == x2);
  84. assert(&std::get<0>(t) == &x);
  85. assert(std::get<1>(t) == y2);
  86. assert(&std::get<1>(t) == &y);
  87. }
  88. {
  89. // test that the implicitly generated move assignment operator
  90. // is properly deleted
  91. using T = std::tuple<std::unique_ptr<int>>;
  92. static_assert(std::is_move_assignable<T>::value, "");
  93. static_assert(!std::is_copy_assignable<T>::value, "");
  94. }
  95. {
  96. using T = std::tuple<int, NonAssignable>;
  97. static_assert(!std::is_move_assignable<T>::value, "");
  98. }
  99. {
  100. using T = std::tuple<int, MoveAssignable>;
  101. static_assert(std::is_move_assignable<T>::value, "");
  102. }
  103. {
  104. // The move should decay to a copy.
  105. CountAssign::reset();
  106. using T = std::tuple<CountAssign, CopyAssignable>;
  107. static_assert(std::is_move_assignable<T>::value, "");
  108. T t1;
  109. T t2;
  110. t1 = std::move(t2);
  111. assert(CountAssign::copied == 1);
  112. assert(CountAssign::moved == 0);
  113. }
  114. return 0;
  115. }