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)83movable function(movable m) 84 { 85 return movable(boost::move_if_noexcept(m)); 86 } 87 function(copy_movable m)88copy_movable function(copy_movable m) 89 { 90 return copy_movable(boost::move_if_noexcept(m)); 91 } 92 function(copy_movable_noexcept m)93copy_movable_noexcept function(copy_movable_noexcept m) 94 { 95 return copy_movable_noexcept(boost::move_if_noexcept(m)); 96 } 97 function(movable_throwable m)98movable_throwable function(movable_throwable m) 99 { 100 return movable_throwable(boost::move_if_noexcept(m)); 101 } 102 functionr(BOOST_RV_REF (movable)m)103movable functionr(BOOST_RV_REF(movable) m) 104 { 105 return movable(boost::move_if_noexcept(m)); 106 } 107 function2(movable m)108movable function2(movable m) 109 { 110 return boost::move_if_noexcept(m); 111 } 112 function2r(BOOST_RV_REF (movable)m)113BOOST_RV_REF(movable) function2r(BOOST_RV_REF(movable) m) 114 { 115 return boost::move_if_noexcept(m); 116 } 117 move_return_function2()118movable move_return_function2 () 119 { 120 return movable(); 121 } 122 move_return_function()123movable 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()131int 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