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