Brian Silverman | 1f5d398 | 2018-08-04 23:37:52 -0700 | [diff] [blame^] | 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: |
| 27 | copy_movable_noexcept() : value_(1){} |
| 28 | |
| 29 | //Move constructor and assignment |
| 30 | copy_movable_noexcept(BOOST_RV_REF(copy_movable_noexcept) m) |
| 31 | { value_ = m.value_; m.value_ = 0; } |
| 32 | |
| 33 | copy_movable_noexcept(const copy_movable_noexcept &m) |
| 34 | { value_ = m.value_; } |
| 35 | |
| 36 | copy_movable_noexcept & operator=(BOOST_RV_REF(copy_movable_noexcept) m) |
| 37 | { value_ = m.value_; m.value_ = 0; return *this; } |
| 38 | |
| 39 | copy_movable_noexcept & operator=(BOOST_COPY_ASSIGN_REF(copy_movable_noexcept) m) |
| 40 | { value_ = m.value_; return *this; } |
| 41 | |
| 42 | 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: |
| 64 | movable_throwable() : value_(1){} |
| 65 | |
| 66 | //Move constructor and assignment |
| 67 | movable_throwable(BOOST_RV_REF(movable_throwable) m) |
| 68 | { value_ = m.value_; m.value_ = 0; } |
| 69 | |
| 70 | movable_throwable & operator=(BOOST_RV_REF(movable_throwable) m) |
| 71 | { value_ = m.value_; m.value_ = 0; return *this; } |
| 72 | |
| 73 | bool moved() const //Observer |
| 74 | { return !value_; } |
| 75 | |
| 76 | int value() const //Observer |
| 77 | { return value_; } |
| 78 | }; |
| 79 | |
| 80 | |
| 81 | ////////////////////////////////////////////////////////////////////////////// |
| 82 | // Helper functions |
| 83 | movable function(movable m) |
| 84 | { |
| 85 | return movable(boost::move_if_noexcept(m)); |
| 86 | } |
| 87 | |
| 88 | copy_movable function(copy_movable m) |
| 89 | { |
| 90 | return copy_movable(boost::move_if_noexcept(m)); |
| 91 | } |
| 92 | |
| 93 | copy_movable_noexcept function(copy_movable_noexcept m) |
| 94 | { |
| 95 | return copy_movable_noexcept(boost::move_if_noexcept(m)); |
| 96 | } |
| 97 | |
| 98 | movable_throwable function(movable_throwable m) |
| 99 | { |
| 100 | return movable_throwable(boost::move_if_noexcept(m)); |
| 101 | } |
| 102 | |
| 103 | movable functionr(BOOST_RV_REF(movable) m) |
| 104 | { |
| 105 | return movable(boost::move_if_noexcept(m)); |
| 106 | } |
| 107 | |
| 108 | movable function2(movable m) |
| 109 | { |
| 110 | return boost::move_if_noexcept(m); |
| 111 | } |
| 112 | |
| 113 | BOOST_RV_REF(movable) function2r(BOOST_RV_REF(movable) m) |
| 114 | { |
| 115 | return boost::move_if_noexcept(m); |
| 116 | } |
| 117 | |
| 118 | movable move_return_function2 () |
| 119 | { |
| 120 | return movable(); |
| 121 | } |
| 122 | |
| 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 | |
| 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> |