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