]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | ////////////////////////////////////////////////////////////////////////////// | |
7c673cae FG |
11 | #include <boost/move/adl_move_swap.hpp> |
12 | #include <boost/move/core.hpp> | |
13 | #include <boost/core/lightweight_test.hpp> | |
14 | ||
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 | ||
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 | ||
36 | unsigned int swap_stats::member_swap_calls = 0; | |
37 | unsigned int swap_stats::friend_swap_calls = 0; | |
38 | unsigned int swap_stats::move_cnstor_calls = 0; | |
39 | unsigned int swap_stats::move_assign_calls = 0; | |
40 | unsigned int swap_stats::copy_cnstor_calls = 0; | |
41 | unsigned int swap_stats::copy_assign_calls = 0; | |
42 | ||
43 | class 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 | ||
53 | class 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 | ||
64 | class 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 | ||
74 | class 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 | ||
87 | int 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 | } |