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/adl_move_swap.hpp>
12#include <boost/move/core.hpp>
13#include <boost/core/lightweight_test.hpp>
14
15class 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
28 static unsigned int member_swap_calls;
29 static unsigned int friend_swap_calls;
30 static unsigned int move_cnstor_calls;
31 static unsigned int move_assign_calls;
32 static unsigned int copy_cnstor_calls;
33 static unsigned int copy_assign_calls;
34};
35
36unsigned int swap_stats::member_swap_calls = 0;
37unsigned int swap_stats::friend_swap_calls = 0;
38unsigned int swap_stats::move_cnstor_calls = 0;
39unsigned int swap_stats::move_assign_calls = 0;
40unsigned int swap_stats::copy_cnstor_calls = 0;
41unsigned int swap_stats::copy_assign_calls = 0;
42
43class movable : public swap_stats
44{
45 BOOST_MOVABLE_BUT_NOT_COPYABLE(movable)
46 public:
47 movable() {}
48 movable(BOOST_RV_REF(movable)) { ++move_cnstor_calls; }
49 movable & operator=(BOOST_RV_REF(movable)){ ++move_assign_calls; return *this; }
50 friend void swap(movable &, movable &) { ++friend_swap_calls; }
51};
52
53class movable_swap_member : public swap_stats
54{
55 BOOST_MOVABLE_BUT_NOT_COPYABLE(movable_swap_member)
56 public:
57 movable_swap_member() {}
58 movable_swap_member(BOOST_RV_REF(movable_swap_member)) { ++move_cnstor_calls; }
59 movable_swap_member & operator=(BOOST_RV_REF(movable_swap_member)){ ++move_assign_calls; return *this; }
60 void swap(movable_swap_member &) { ++member_swap_calls; }
61 friend void swap(movable_swap_member &, movable_swap_member &) { ++friend_swap_calls; }
62};
63
64class copyable : public swap_stats
65{
66 public:
67 copyable() {}
68 copyable(const copyable &) { ++copy_cnstor_calls; }
69 copyable & operator=(const copyable&) { ++copy_assign_calls; return *this; }
70 void swap(copyable &) { ++member_swap_calls; }
71 friend void swap(copyable &, copyable &) { ++friend_swap_calls; }
72};
73
74class no_swap : public swap_stats
75{
76 private: unsigned m_state;
77 public:
78 explicit no_swap(unsigned i): m_state(i){}
79 no_swap(const no_swap &x) { m_state = x.m_state; ++copy_cnstor_calls; }
80 no_swap & operator=(const no_swap& x) { m_state = x.m_state; ++copy_assign_calls; return *this; }
81 void swap(no_swap &) { ++member_swap_calls; }
82 friend bool operator==(const no_swap &x, const no_swap &y) { return x.m_state == y.m_state; }
83 friend bool operator!=(const no_swap &x, const no_swap &y) { return !(x==y); }
84};
85
86
87int main()
88{
89 { //movable
90 movable x, y;
91 swap_stats::reset_stats();
92 ::boost::adl_move_swap(x, y);
93 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
94 //In non rvalue reference compilers,
95 //movable classes with no swap() member uses
96 //boost::move() to implement swap.
97 BOOST_TEST(swap_stats::friend_swap_calls == 0);
98 BOOST_TEST(swap_stats::member_swap_calls == 0);
99 BOOST_TEST(swap_stats::member_swap_calls == 0);
100 BOOST_TEST(swap_stats::move_cnstor_calls == 1);
101 BOOST_TEST(swap_stats::move_assign_calls == 2);
102 BOOST_TEST(swap_stats::copy_cnstor_calls == 0);
103 BOOST_TEST(swap_stats::copy_assign_calls == 0);
104 #else
105 //In compilers with rvalue references, this should call friend swap via ADL
106 BOOST_TEST(swap_stats::friend_swap_calls == 1);
107 BOOST_TEST(swap_stats::member_swap_calls == 0);
108 BOOST_TEST(swap_stats::member_swap_calls == 0);
109 BOOST_TEST(swap_stats::move_cnstor_calls == 0);
110 BOOST_TEST(swap_stats::move_assign_calls == 0);
111 BOOST_TEST(swap_stats::copy_cnstor_calls == 0);
112 BOOST_TEST(swap_stats::copy_assign_calls == 0);
113 #endif
114 }
115 { //movable_swap_member
116 movable_swap_member x, y;
117 swap_stats::reset_stats();
118 ::boost::adl_move_swap(x, y);
119 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
120 //In non rvalue reference compilers,
121 //movable classes with no swap() member uses
122 //boost::move() to implement swap.
123 BOOST_TEST(swap_stats::friend_swap_calls == 0);
124 BOOST_TEST(swap_stats::member_swap_calls == 1);
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 #else
130 //In compilers with rvalue references, this should call friend swap via ADL
131 BOOST_TEST(swap_stats::friend_swap_calls == 1);
132 BOOST_TEST(swap_stats::member_swap_calls == 0);
133 BOOST_TEST(swap_stats::move_cnstor_calls == 0);
134 BOOST_TEST(swap_stats::move_assign_calls == 0);
135 BOOST_TEST(swap_stats::copy_cnstor_calls == 0);
136 BOOST_TEST(swap_stats::copy_assign_calls == 0);
137 #endif
138 }
139 { //copyable
140 copyable x, y;
141 swap_stats::reset_stats();
142 ::boost::adl_move_swap(x, y);
143 //This should call friend swap via ADL
144 BOOST_TEST(swap_stats::friend_swap_calls == 1);
145 BOOST_TEST(swap_stats::member_swap_calls == 0);
146 BOOST_TEST(swap_stats::move_cnstor_calls == 0);
147 BOOST_TEST(swap_stats::move_assign_calls == 0);
148 BOOST_TEST(swap_stats::copy_cnstor_calls == 0);
149 BOOST_TEST(swap_stats::copy_assign_calls == 0);
150 }
151 { //no_swap
152 no_swap x(1), y(2), x_back(x), y_back(y);
153 swap_stats::reset_stats();
154 ::boost::adl_move_swap(x, y);
155 //This should call std::swap which uses copies
156 BOOST_TEST(swap_stats::friend_swap_calls == 0);
157 BOOST_TEST(swap_stats::member_swap_calls == 0);
158 BOOST_TEST(swap_stats::move_cnstor_calls == 0);
159 BOOST_TEST(swap_stats::move_assign_calls == 0);
160 BOOST_TEST(swap_stats::copy_cnstor_calls == 1);
161 BOOST_TEST(swap_stats::copy_assign_calls == 2);
162 BOOST_TEST(x == y_back);
163 BOOST_TEST(y == x_back);
164 BOOST_TEST(x != y);
165 }
166 return ::boost::report_errors();
167}
168

source code of boost/libs/move/test/adl_move_swap.cpp