1 | ////////////////////////////////////////////////////////////////////////////// |
---|---|
2 | // |
3 | // (C) Copyright Antony Polukhin 2014. |
4 | // (C) Copyright Ion Gaztanaga 2014. |
5 | // Distributed under the Boost Software License, Version 1.0. |
6 | // (See accompanying file LICENSE_1_0.txt or copy at |
7 | // http://www.boost.org/LICENSE_1_0.txt) |
8 | // |
9 | // See http://www.boost.org/libs/move for documentation. |
10 | // |
11 | ////////////////////////////////////////////////////////////////////////////// |
12 | |
13 | #include <boost/move/utility.hpp> |
14 | #include <boost/core/lightweight_test.hpp> |
15 | #include "../example/movable.hpp" |
16 | #include "../example/copymovable.hpp" |
17 | |
18 | ////////////////////////////////////////////////////////////////////////////// |
19 | //A copy_movable_noexcept class |
20 | class copy_movable_noexcept |
21 | { |
22 | BOOST_COPYABLE_AND_MOVABLE(copy_movable_noexcept) |
23 | int value_; |
24 | |
25 | public: |
26 | copy_movable_noexcept() : value_(1){} |
27 | |
28 | //Move constructor and assignment |
29 | copy_movable_noexcept(BOOST_RV_REF(copy_movable_noexcept) m) |
30 | { value_ = m.value_; m.value_ = 0; } |
31 | |
32 | copy_movable_noexcept(const copy_movable_noexcept &m) |
33 | { value_ = m.value_; } |
34 | |
35 | copy_movable_noexcept & operator=(BOOST_RV_REF(copy_movable_noexcept) m) |
36 | { value_ = m.value_; m.value_ = 0; return *this; } |
37 | |
38 | copy_movable_noexcept & operator=(BOOST_COPY_ASSIGN_REF(copy_movable_noexcept) m) |
39 | { value_ = m.value_; return *this; } |
40 | |
41 | bool moved() const //Observer |
42 | { return value_ == 0; } |
43 | }; |
44 | |
45 | namespace boost{ |
46 | |
47 | template<> |
48 | struct has_nothrow_move<copy_movable_noexcept> |
49 | { |
50 | static const bool value = true; |
51 | }; |
52 | |
53 | } //namespace boost{ |
54 | |
55 | ////////////////////////////////////////////////////////////////////////////// |
56 | //A movable_throwable class |
57 | class movable_throwable |
58 | { |
59 | BOOST_MOVABLE_BUT_NOT_COPYABLE(movable_throwable) |
60 | int value_; |
61 | |
62 | public: |
63 | movable_throwable() : value_(1){} |
64 | |
65 | //Move constructor and assignment |
66 | movable_throwable(BOOST_RV_REF(movable_throwable) m) |
67 | { value_ = m.value_; m.value_ = 0; } |
68 | |
69 | movable_throwable & operator=(BOOST_RV_REF(movable_throwable) m) |
70 | { value_ = m.value_; m.value_ = 0; return *this; } |
71 | |
72 | bool moved() const //Observer |
73 | { return !value_; } |
74 | |
75 | int value() const //Observer |
76 | { return value_; } |
77 | }; |
78 | |
79 | |
80 | ////////////////////////////////////////////////////////////////////////////// |
81 | // Helper functions |
82 | movable function(movable m) |
83 | { |
84 | return movable(boost::move_if_noexcept(x&: m)); |
85 | } |
86 | |
87 | copy_movable function(copy_movable m) |
88 | { |
89 | return copy_movable(boost::move_if_noexcept(x&: m)); |
90 | } |
91 | |
92 | copy_movable_noexcept function(copy_movable_noexcept m) |
93 | { |
94 | return copy_movable_noexcept(boost::move_if_noexcept(x&: m)); |
95 | } |
96 | |
97 | movable_throwable function(movable_throwable m) |
98 | { |
99 | return movable_throwable(boost::move_if_noexcept(x&: m)); |
100 | } |
101 | |
102 | movable functionr(BOOST_RV_REF(movable) m) |
103 | { |
104 | return movable(boost::move_if_noexcept(x&: m)); |
105 | } |
106 | |
107 | movable function2(movable m) |
108 | { |
109 | return boost::move_if_noexcept(x&: m); |
110 | } |
111 | |
112 | BOOST_RV_REF(movable) function2r(BOOST_RV_REF(movable) m) |
113 | { |
114 | return boost::move_if_noexcept(x&: m); |
115 | } |
116 | |
117 | movable move_return_function2 () |
118 | { |
119 | return movable(); |
120 | } |
121 | |
122 | movable move_return_function () |
123 | { |
124 | movable m; |
125 | return (boost::move_if_noexcept(x&: m)); |
126 | } |
127 | |
128 | #define BOOST_CHECK(x) if (!(x)) { return __LINE__; } |
129 | |
130 | int main() |
131 | { |
132 | { |
133 | movable m; |
134 | movable m2(boost::move_if_noexcept(x&: m)); |
135 | BOOST_CHECK(m.moved()); |
136 | movable m3(function(m: movable(boost::move_if_noexcept(x&: m2)))); |
137 | BOOST_CHECK(m2.moved()); |
138 | movable m4(function(m: boost::move_if_noexcept(x&: m3))); |
139 | BOOST_CHECK(m3.moved()); |
140 | BOOST_CHECK(!m4.moved()); |
141 | } |
142 | { |
143 | movable m; |
144 | movable m2(boost::move_if_noexcept(x&: m)); |
145 | BOOST_CHECK(m.moved()); |
146 | movable m3(functionr(m: movable(boost::move_if_noexcept(x&: m2)))); |
147 | BOOST_CHECK(m2.moved()); |
148 | movable m4(functionr(m: boost::move_if_noexcept(x&: m3))); |
149 | BOOST_CHECK(m3.moved()); |
150 | BOOST_CHECK(!m4.moved()); |
151 | } |
152 | { |
153 | movable m; |
154 | movable m2(boost::move_if_noexcept(x&: m)); |
155 | BOOST_CHECK(m.moved()); |
156 | movable m3(function2(m: movable(boost::move_if_noexcept(x&: m2)))); |
157 | BOOST_CHECK(m2.moved()); |
158 | movable m4(function2(m: boost::move_if_noexcept(x&: m3))); |
159 | BOOST_CHECK(m3.moved()); |
160 | BOOST_CHECK(!m4.moved()); |
161 | } |
162 | { |
163 | movable m; |
164 | movable m2(boost::move_if_noexcept(x&: m)); |
165 | BOOST_CHECK(m.moved()); |
166 | movable m3(function2r(m: movable(boost::move_if_noexcept(x&: m2)))); |
167 | BOOST_CHECK(m2.moved()); |
168 | movable m4(function2r(m: boost::move_if_noexcept(x&: m3))); |
169 | BOOST_CHECK(m3.moved()); |
170 | BOOST_CHECK(!m4.moved()); |
171 | } |
172 | { |
173 | movable m; |
174 | movable m2(boost::move_if_noexcept(x&: m)); |
175 | BOOST_CHECK(m.moved()); |
176 | BOOST_CHECK(!m2.moved()); |
177 | movable m3(move_return_function()); |
178 | BOOST_CHECK(!m3.moved()); |
179 | } |
180 | { |
181 | movable m; |
182 | movable m2(boost::move_if_noexcept(x&: m)); |
183 | BOOST_CHECK(m.moved()); |
184 | BOOST_CHECK(!m2.moved()); |
185 | movable m3(move_return_function2()); |
186 | BOOST_CHECK(!m3.moved()); |
187 | } |
188 | |
189 | // copy_movable may throw during move, so it must be copied |
190 | { |
191 | copy_movable m; |
192 | copy_movable m2(boost::move_if_noexcept(x&: m)); |
193 | BOOST_CHECK(!m.moved()); |
194 | copy_movable m3(function(m: copy_movable(boost::move_if_noexcept(x&: m2)))); |
195 | BOOST_CHECK(!m2.moved()); |
196 | copy_movable m4(function(m: boost::move_if_noexcept(x&: m3))); |
197 | BOOST_CHECK(!m3.moved()); |
198 | BOOST_CHECK(!m4.moved()); |
199 | } |
200 | |
201 | |
202 | // copy_movable_noexcept can not throw during move |
203 | { |
204 | copy_movable_noexcept m; |
205 | copy_movable_noexcept m2(boost::move_if_noexcept(x&: m)); |
206 | BOOST_CHECK(m.moved()); |
207 | copy_movable_noexcept m3(function(m: copy_movable_noexcept(boost::move_if_noexcept(x&: m2)))); |
208 | BOOST_CHECK(m2.moved()); |
209 | copy_movable_noexcept m4(function(m: boost::move_if_noexcept(x&: m3))); |
210 | BOOST_CHECK(m3.moved()); |
211 | BOOST_CHECK(!m4.moved()); |
212 | } |
213 | |
214 | // movable_throwable can not throw during move but it has no copy constructor |
215 | { |
216 | movable_throwable m; |
217 | movable_throwable m2(boost::move_if_noexcept(x&: m)); |
218 | BOOST_CHECK(m.moved()); |
219 | movable_throwable m3(function(m: movable_throwable(boost::move_if_noexcept(x&: m2)))); |
220 | BOOST_CHECK(m2.moved()); |
221 | movable_throwable m4(function(m: boost::move_if_noexcept(x&: m3))); |
222 | BOOST_CHECK(m3.moved()); |
223 | BOOST_CHECK(!m4.moved()); |
224 | } |
225 | |
226 | return boost::report_errors(); |
227 | } |
228 |