move.pass.cpp 3.4 KB

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