| 1 | #include <boost/config.hpp> |
| 2 | |
| 3 | #if defined(BOOST_MSVC) |
| 4 | |
| 5 | #pragma warning(disable: 4786) // identifier truncated in debug info |
| 6 | #pragma warning(disable: 4710) // function not inlined |
| 7 | #pragma warning(disable: 4711) // function selected for automatic inline expansion |
| 8 | #pragma warning(disable: 4514) // unreferenced inline removed |
| 9 | #pragma warning(disable: 4355) // 'this' : used in base member initializer list |
| 10 | |
| 11 | #if (BOOST_MSVC >= 1310) |
| 12 | #pragma warning(disable: 4675) // resolved overload found with Koenig lookup |
| 13 | #endif |
| 14 | |
| 15 | #endif |
| 16 | |
| 17 | #if defined(__GNUC__) && __GNUC__ > 4 |
| 18 | # pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor" |
| 19 | #endif |
| 20 | |
| 21 | // |
| 22 | // shared_ptr_basic_test.cpp |
| 23 | // |
| 24 | // Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. |
| 25 | // |
| 26 | // Distributed under the Boost Software License, Version 1.0. (See |
| 27 | // accompanying file LICENSE_1_0.txt or copy at |
| 28 | // http://www.boost.org/LICENSE_1_0.txt) |
| 29 | // |
| 30 | |
| 31 | #include <boost/core/lightweight_test.hpp> |
| 32 | |
| 33 | #include <boost/shared_ptr.hpp> |
| 34 | #include <boost/weak_ptr.hpp> |
| 35 | |
| 36 | int cnt = 0; |
| 37 | |
| 38 | struct X |
| 39 | { |
| 40 | X() |
| 41 | { |
| 42 | ++cnt; |
| 43 | } |
| 44 | |
| 45 | ~X() // virtual destructor deliberately omitted |
| 46 | { |
| 47 | --cnt; |
| 48 | } |
| 49 | |
| 50 | virtual int id() const |
| 51 | { |
| 52 | return 1; |
| 53 | } |
| 54 | |
| 55 | private: |
| 56 | |
| 57 | X(X const &); |
| 58 | X & operator= (X const &); |
| 59 | }; |
| 60 | |
| 61 | struct Y: public X |
| 62 | { |
| 63 | Y() |
| 64 | { |
| 65 | ++cnt; |
| 66 | } |
| 67 | |
| 68 | ~Y() |
| 69 | { |
| 70 | --cnt; |
| 71 | } |
| 72 | |
| 73 | virtual int id() const |
| 74 | { |
| 75 | return 2; |
| 76 | } |
| 77 | |
| 78 | private: |
| 79 | |
| 80 | Y(Y const &); |
| 81 | Y & operator= (Y const &); |
| 82 | }; |
| 83 | |
| 84 | int * get_object() |
| 85 | { |
| 86 | ++cnt; |
| 87 | return &cnt; |
| 88 | } |
| 89 | |
| 90 | void release_object(int * p) |
| 91 | { |
| 92 | BOOST_TEST(p == &cnt); |
| 93 | --cnt; |
| 94 | } |
| 95 | |
| 96 | template<class T> void test_is_X(boost::shared_ptr<T> const & p) |
| 97 | { |
| 98 | BOOST_TEST(p->id() == 1); |
| 99 | BOOST_TEST((*p).id() == 1); |
| 100 | } |
| 101 | |
| 102 | template<class T> void test_is_X(boost::weak_ptr<T> const & p) |
| 103 | { |
| 104 | BOOST_TEST(p.get() != 0); |
| 105 | BOOST_TEST(p.get()->id() == 1); |
| 106 | } |
| 107 | |
| 108 | template<class T> void test_is_Y(boost::shared_ptr<T> const & p) |
| 109 | { |
| 110 | BOOST_TEST(p->id() == 2); |
| 111 | BOOST_TEST((*p).id() == 2); |
| 112 | } |
| 113 | |
| 114 | template<class T> void test_is_Y(boost::weak_ptr<T> const & p) |
| 115 | { |
| 116 | boost::shared_ptr<T> q = p.lock(); |
| 117 | BOOST_TEST(q.get() != 0); |
| 118 | BOOST_TEST(q->id() == 2); |
| 119 | } |
| 120 | |
| 121 | template<class T> void test_eq(T const & a, T const & b) |
| 122 | { |
| 123 | BOOST_TEST(a == b); |
| 124 | BOOST_TEST(!(a != b)); |
| 125 | BOOST_TEST(!(a < b)); |
| 126 | BOOST_TEST(!(b < a)); |
| 127 | } |
| 128 | |
| 129 | template<class T> void test_ne(T const & a, T const & b) |
| 130 | { |
| 131 | BOOST_TEST(!(a == b)); |
| 132 | BOOST_TEST(a != b); |
| 133 | BOOST_TEST(a < b || b < a); |
| 134 | BOOST_TEST(!(a < b && b < a)); |
| 135 | } |
| 136 | |
| 137 | template<class T, class U> void test_shared(boost::weak_ptr<T> const & a, boost::weak_ptr<U> const & b) |
| 138 | { |
| 139 | BOOST_TEST(!(a < b)); |
| 140 | BOOST_TEST(!(b < a)); |
| 141 | } |
| 142 | |
| 143 | template<class T, class U> void test_nonshared(boost::weak_ptr<T> const & a, boost::weak_ptr<U> const & b) |
| 144 | { |
| 145 | BOOST_TEST(a < b || b < a); |
| 146 | BOOST_TEST(!(a < b && b < a)); |
| 147 | } |
| 148 | |
| 149 | template<class T, class U> void test_eq2(T const & a, U const & b) |
| 150 | { |
| 151 | BOOST_TEST(a == b); |
| 152 | BOOST_TEST(!(a != b)); |
| 153 | } |
| 154 | |
| 155 | template<class T, class U> void test_ne2(T const & a, U const & b) |
| 156 | { |
| 157 | BOOST_TEST(!(a == b)); |
| 158 | BOOST_TEST(a != b); |
| 159 | } |
| 160 | |
| 161 | template<class T> void test_is_zero(boost::shared_ptr<T> const & p) |
| 162 | { |
| 163 | BOOST_TEST(!p); |
| 164 | BOOST_TEST(p.get() == 0); |
| 165 | } |
| 166 | |
| 167 | template<class T> void test_is_nonzero(boost::shared_ptr<T> const & p) |
| 168 | { |
| 169 | // p? true: false is used to test p in a boolean context. |
| 170 | // BOOST_TEST(p) is not guaranteed to test the conversion, |
| 171 | // as the macro might test !!p instead. |
| 172 | BOOST_TEST(p? true: false); |
| 173 | BOOST_TEST(p.get() != 0); |
| 174 | } |
| 175 | |
| 176 | int main() |
| 177 | { |
| 178 | using namespace boost; |
| 179 | |
| 180 | { |
| 181 | shared_ptr<X> p(new Y); |
| 182 | shared_ptr<X> p2(new X); |
| 183 | |
| 184 | test_is_nonzero(p); |
| 185 | test_is_nonzero(p: p2); |
| 186 | test_is_Y(p); |
| 187 | test_is_X(p: p2); |
| 188 | test_ne(a: p, b: p2); |
| 189 | |
| 190 | { |
| 191 | shared_ptr<X> q(p); |
| 192 | test_eq(a: p, b: q); |
| 193 | } |
| 194 | |
| 195 | #if !defined( BOOST_NO_RTTI ) |
| 196 | shared_ptr<Y> p3 = dynamic_pointer_cast<Y>(r: p); |
| 197 | shared_ptr<Y> p4 = dynamic_pointer_cast<Y>(r: p2); |
| 198 | |
| 199 | test_is_nonzero(p: p3); |
| 200 | test_is_zero(p: p4); |
| 201 | |
| 202 | BOOST_TEST(p.use_count() == 2); |
| 203 | BOOST_TEST(p2.use_count() == 1); |
| 204 | BOOST_TEST(p3.use_count() == 2); |
| 205 | |
| 206 | test_is_Y(p: p3); |
| 207 | test_eq2(a: p, b: p3); |
| 208 | test_ne2(a: p2, b: p4); |
| 209 | #endif |
| 210 | |
| 211 | shared_ptr<void> p5(p); |
| 212 | |
| 213 | test_is_nonzero(p: p5); |
| 214 | test_eq2(a: p, b: p5); |
| 215 | |
| 216 | weak_ptr<X> wp1(p2); |
| 217 | |
| 218 | BOOST_TEST(!wp1.expired()); |
| 219 | BOOST_TEST(wp1.use_count() != 0); |
| 220 | |
| 221 | p.reset(); |
| 222 | p2.reset(); |
| 223 | #if !defined( BOOST_NO_RTTI ) |
| 224 | p3.reset(); |
| 225 | p4.reset(); |
| 226 | #endif |
| 227 | |
| 228 | test_is_zero(p); |
| 229 | test_is_zero(p: p2); |
| 230 | #if !defined( BOOST_NO_RTTI ) |
| 231 | test_is_zero(p: p3); |
| 232 | test_is_zero(p: p4); |
| 233 | #endif |
| 234 | |
| 235 | BOOST_TEST(p5.use_count() == 1); |
| 236 | |
| 237 | BOOST_TEST(wp1.expired()); |
| 238 | BOOST_TEST(wp1.use_count() == 0); |
| 239 | |
| 240 | try |
| 241 | { |
| 242 | shared_ptr<X> sp1(wp1); |
| 243 | BOOST_ERROR("shared_ptr<X> sp1(wp1) failed to throw" ); |
| 244 | } |
| 245 | catch(boost::bad_weak_ptr const &) |
| 246 | { |
| 247 | } |
| 248 | |
| 249 | test_is_zero(p: wp1.lock()); |
| 250 | |
| 251 | weak_ptr<X> wp2 = static_pointer_cast<X>(r: p5); |
| 252 | |
| 253 | BOOST_TEST(wp2.use_count() == 1); |
| 254 | test_is_Y(p: wp2); |
| 255 | test_nonshared(a: wp1, b: wp2); |
| 256 | |
| 257 | // Scoped to not affect the subsequent use_count() tests. |
| 258 | { |
| 259 | shared_ptr<X> sp2(wp2); |
| 260 | test_is_nonzero(p: wp2.lock()); |
| 261 | } |
| 262 | |
| 263 | #if !defined( BOOST_NO_RTTI ) |
| 264 | weak_ptr<Y> wp3 = dynamic_pointer_cast<Y>(r: wp2.lock()); |
| 265 | |
| 266 | BOOST_TEST(wp3.use_count() == 1); |
| 267 | test_shared(a: wp2, b: wp3); |
| 268 | |
| 269 | weak_ptr<X> wp4(wp3); |
| 270 | |
| 271 | BOOST_TEST(wp4.use_count() == 1); |
| 272 | test_shared(a: wp2, b: wp4); |
| 273 | #endif |
| 274 | |
| 275 | wp1 = p2; |
| 276 | test_is_zero(p: wp1.lock()); |
| 277 | |
| 278 | #if !defined( BOOST_NO_RTTI ) |
| 279 | wp1 = p4; |
| 280 | wp1 = wp3; |
| 281 | #endif |
| 282 | wp1 = wp2; |
| 283 | |
| 284 | BOOST_TEST(wp1.use_count() == 1); |
| 285 | test_shared(a: wp1, b: wp2); |
| 286 | |
| 287 | weak_ptr<X> wp5; |
| 288 | |
| 289 | bool b1 = wp1 < wp5; |
| 290 | bool b2 = wp5 < wp1; |
| 291 | |
| 292 | p5.reset(); |
| 293 | |
| 294 | BOOST_TEST(wp1.use_count() == 0); |
| 295 | BOOST_TEST(wp2.use_count() == 0); |
| 296 | #if !defined( BOOST_NO_RTTI ) |
| 297 | BOOST_TEST(wp3.use_count() == 0); |
| 298 | #endif |
| 299 | |
| 300 | // Test operator< stability for std::set< weak_ptr<> > |
| 301 | // Thanks to Joe Gottman for pointing this out |
| 302 | |
| 303 | BOOST_TEST(b1 == (wp1 < wp5)); |
| 304 | BOOST_TEST(b2 == (wp5 < wp1)); |
| 305 | |
| 306 | { |
| 307 | // note that both get_object and release_object deal with int* |
| 308 | shared_ptr<void> p6(get_object(), release_object); |
| 309 | } |
| 310 | } |
| 311 | |
| 312 | BOOST_TEST(cnt == 0); |
| 313 | |
| 314 | return boost::report_errors(); |
| 315 | } |
| 316 | |