adl_move_swap.cpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2014-2014.
  4. // Distributed under the Boost Software License, Version 1.0.
  5. // (See accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. //
  8. // See http://www.boost.org/libs/move for documentation.
  9. //
  10. //////////////////////////////////////////////////////////////////////////////
  11. #include <boost/move/detail/config_begin.hpp>
  12. #include <boost/move/adl_move_swap.hpp>
  13. #include <boost/move/core.hpp>
  14. #include <boost/core/lightweight_test.hpp>
  15. class swap_stats
  16. {
  17. public:
  18. static void reset_stats()
  19. {
  20. member_swap_calls = 0;
  21. friend_swap_calls = 0;
  22. move_cnstor_calls = 0;
  23. move_assign_calls = 0;
  24. copy_cnstor_calls = 0;
  25. copy_assign_calls = 0;
  26. }
  27. static unsigned int member_swap_calls;
  28. static unsigned int friend_swap_calls;
  29. static unsigned int move_cnstor_calls;
  30. static unsigned int move_assign_calls;
  31. static unsigned int copy_cnstor_calls;
  32. static unsigned int copy_assign_calls;
  33. };
  34. unsigned int swap_stats::member_swap_calls = 0;
  35. unsigned int swap_stats::friend_swap_calls = 0;
  36. unsigned int swap_stats::move_cnstor_calls = 0;
  37. unsigned int swap_stats::move_assign_calls = 0;
  38. unsigned int swap_stats::copy_cnstor_calls = 0;
  39. unsigned int swap_stats::copy_assign_calls = 0;
  40. class movable : public swap_stats
  41. {
  42. BOOST_MOVABLE_BUT_NOT_COPYABLE(movable)
  43. public:
  44. movable() {}
  45. movable(BOOST_RV_REF(movable)) { ++move_cnstor_calls; }
  46. movable & operator=(BOOST_RV_REF(movable)){ ++move_assign_calls; return *this; }
  47. friend void swap(movable &, movable &) { ++friend_swap_calls; }
  48. };
  49. class movable_swap_member : public swap_stats
  50. {
  51. BOOST_MOVABLE_BUT_NOT_COPYABLE(movable_swap_member)
  52. public:
  53. movable_swap_member() {}
  54. movable_swap_member(BOOST_RV_REF(movable_swap_member)) { ++move_cnstor_calls; }
  55. movable_swap_member & operator=(BOOST_RV_REF(movable_swap_member)){ ++move_assign_calls; return *this; }
  56. void swap(movable_swap_member &) { ++member_swap_calls; }
  57. friend void swap(movable_swap_member &, movable_swap_member &) { ++friend_swap_calls; }
  58. };
  59. class copyable : public swap_stats
  60. {
  61. public:
  62. copyable() {}
  63. copyable(const copyable &) { ++copy_cnstor_calls; }
  64. copyable & operator=(const copyable&) { ++copy_assign_calls; return *this; }
  65. void swap(copyable &) { ++member_swap_calls; }
  66. friend void swap(copyable &, copyable &) { ++friend_swap_calls; }
  67. };
  68. class no_swap : public swap_stats
  69. {
  70. private: unsigned m_state;
  71. public:
  72. explicit no_swap(unsigned i): m_state(i){}
  73. no_swap(const no_swap &x) { m_state = x.m_state; ++copy_cnstor_calls; }
  74. no_swap & operator=(const no_swap& x) { m_state = x.m_state; ++copy_assign_calls; return *this; }
  75. void swap(no_swap &) { ++member_swap_calls; }
  76. friend bool operator==(const no_swap &x, const no_swap &y) { return x.m_state == y.m_state; }
  77. friend bool operator!=(const no_swap &x, const no_swap &y) { return !(x==y); }
  78. };
  79. int main()
  80. {
  81. { //movable
  82. movable x, y;
  83. swap_stats::reset_stats();
  84. ::boost::adl_move_swap(x, y);
  85. #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
  86. //In non rvalue reference compilers,
  87. //movable classes with no swap() member uses
  88. //boost::move() to implement swap.
  89. BOOST_TEST(swap_stats::friend_swap_calls == 0);
  90. BOOST_TEST(swap_stats::member_swap_calls == 0);
  91. BOOST_TEST(swap_stats::member_swap_calls == 0);
  92. BOOST_TEST(swap_stats::move_cnstor_calls == 1);
  93. BOOST_TEST(swap_stats::move_assign_calls == 2);
  94. BOOST_TEST(swap_stats::copy_cnstor_calls == 0);
  95. BOOST_TEST(swap_stats::copy_assign_calls == 0);
  96. #else
  97. //In compilers with rvalue references, this should call friend swap via ADL
  98. BOOST_TEST(swap_stats::friend_swap_calls == 1);
  99. BOOST_TEST(swap_stats::member_swap_calls == 0);
  100. BOOST_TEST(swap_stats::member_swap_calls == 0);
  101. BOOST_TEST(swap_stats::move_cnstor_calls == 0);
  102. BOOST_TEST(swap_stats::move_assign_calls == 0);
  103. BOOST_TEST(swap_stats::copy_cnstor_calls == 0);
  104. BOOST_TEST(swap_stats::copy_assign_calls == 0);
  105. #endif
  106. }
  107. { //movable_swap_member
  108. movable_swap_member x, y;
  109. swap_stats::reset_stats();
  110. ::boost::adl_move_swap(x, y);
  111. #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
  112. //In non rvalue reference compilers,
  113. //movable classes with no swap() member uses
  114. //boost::move() to implement swap.
  115. BOOST_TEST(swap_stats::friend_swap_calls == 0);
  116. BOOST_TEST(swap_stats::member_swap_calls == 1);
  117. BOOST_TEST(swap_stats::move_cnstor_calls == 0);
  118. BOOST_TEST(swap_stats::move_assign_calls == 0);
  119. BOOST_TEST(swap_stats::copy_cnstor_calls == 0);
  120. BOOST_TEST(swap_stats::copy_assign_calls == 0);
  121. #else
  122. //In compilers with rvalue references, this should call friend swap via ADL
  123. BOOST_TEST(swap_stats::friend_swap_calls == 1);
  124. BOOST_TEST(swap_stats::member_swap_calls == 0);
  125. BOOST_TEST(swap_stats::move_cnstor_calls == 0);
  126. BOOST_TEST(swap_stats::move_assign_calls == 0);
  127. BOOST_TEST(swap_stats::copy_cnstor_calls == 0);
  128. BOOST_TEST(swap_stats::copy_assign_calls == 0);
  129. #endif
  130. }
  131. { //copyable
  132. copyable x, y;
  133. swap_stats::reset_stats();
  134. ::boost::adl_move_swap(x, y);
  135. //This should call friend swap via ADL
  136. BOOST_TEST(swap_stats::friend_swap_calls == 1);
  137. BOOST_TEST(swap_stats::member_swap_calls == 0);
  138. BOOST_TEST(swap_stats::move_cnstor_calls == 0);
  139. BOOST_TEST(swap_stats::move_assign_calls == 0);
  140. BOOST_TEST(swap_stats::copy_cnstor_calls == 0);
  141. BOOST_TEST(swap_stats::copy_assign_calls == 0);
  142. }
  143. { //no_swap
  144. no_swap x(1), y(2), x_back(x), y_back(y);
  145. swap_stats::reset_stats();
  146. ::boost::adl_move_swap(x, y);
  147. //This should call std::swap which uses copies
  148. BOOST_TEST(swap_stats::friend_swap_calls == 0);
  149. BOOST_TEST(swap_stats::member_swap_calls == 0);
  150. BOOST_TEST(swap_stats::move_cnstor_calls == 0);
  151. BOOST_TEST(swap_stats::move_assign_calls == 0);
  152. BOOST_TEST(swap_stats::copy_cnstor_calls == 1);
  153. BOOST_TEST(swap_stats::copy_assign_calls == 2);
  154. BOOST_TEST(x == y_back);
  155. BOOST_TEST(y == x_back);
  156. BOOST_TEST(x != y);
  157. }
  158. return ::boost::report_errors();
  159. }
  160. #include <boost/move/detail/config_end.hpp>