1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
|
//
// cpp11_pointer_cast_test.cpp - a test for boost/pointer_cast.hpp with std::shared_ptr and std::unique_ptr
//
// Copyright (c) 2016 Karolin Varner
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/pointer_cast.hpp>
#include <boost/config.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/get_pointer.hpp>
#include <boost/shared_ptr.hpp>
#include <memory>
#include <utility>
#include <functional>
#if defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) \
|| defined( BOOST_NO_CXX11_HDR_FUNCTIONAL ) \
|| defined( BOOST_NO_CXX11_HDR_UTILITY ) \
|| defined( BOOST_NO_CXX11_LAMBDAS ) \
|| defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
// We expect all the features or none of the features to be
// available, since we should be on C++11
int main() { return 0; }
#else
namespace
{
// Let's create these inheritance relationship:
//
// base base2
// | |
// derived
// |
// derived_derived
//
class base
{
public:
virtual ~base(){}
int filler [5];
};
class base2
{
public:
virtual ~base2(){}
int filler [5];
};
class derived
: public base, public base2
{
int filler [5];
};
class derived_derived
: public derived
{
int filler [5];
};
// And now some simple check functions
#if !defined( BOOST_NO_RTTI )
template <class BasePtr>
bool check_dynamic_pointer_cast(const BasePtr &ptr)
{
//Check that dynamic_pointer_cast versus dynamic_cast
return
//Correct cast with dynamic_pointer_cast
boost::get_pointer(boost::dynamic_pointer_cast<derived>(ptr)) ==
//Correct cast with dynamic_cast
dynamic_cast<derived*>(boost::get_pointer(ptr))
&&
//Incorrect cast with dynamic_pointer_cast
boost::get_pointer(boost::dynamic_pointer_cast<derived_derived>(ptr)) ==
//Incorrect cast with dynamic_cast
dynamic_cast<derived_derived*>(boost::get_pointer(ptr));
}
#endif
template <class BasePtr>
bool check_static_pointer_cast(const BasePtr &ptr)
{
return
//Cast base -> derived -> base2 using static_pointer_cast
boost::get_pointer(
boost::static_pointer_cast<base2>(
boost::static_pointer_cast<derived>(ptr))) ==
//Now the same with static_cast
static_cast<base2*>(static_cast<derived*>(boost::get_pointer(ptr)));
}
template <class BasePtr>
bool check_const_pointer_cast(const BasePtr &ptr)
{
return
//Unconst and const again using const_pointer_cast
boost::get_pointer(
boost::const_pointer_cast<const base>
(boost::const_pointer_cast<base>(ptr))) ==
//Now the same with const_cast
const_cast<const base*>(const_cast<base*>(boost::get_pointer(ptr)));
}
template <class BasePtr>
void check_all_copy_casts(const BasePtr &ptr)
{
#if !defined( BOOST_NO_RTTI )
BOOST_TEST( check_dynamic_pointer_cast( ptr ) );
#endif
BOOST_TEST( check_static_pointer_cast( ptr ) );
BOOST_TEST( check_const_pointer_cast( ptr ) );
}
#if !defined( BOOST_NO_RTTI )
template <class BasePtr>
bool check_dynamic_moving_pointer_cast(std::function<BasePtr()> f)
{
BasePtr smart1 = f(), smart2 = f();
derived* expect1 = dynamic_cast<derived*>(boost::get_pointer(smart1));
derived_derived* expect2 = dynamic_cast<derived_derived*>(boost::get_pointer(smart2));
//Check that dynamic_pointer_cast versus dynamic_cast
return
//Correct cast with dynamic_pointer_cast
boost::get_pointer(boost::dynamic_pointer_cast<derived>( std::move(smart1) )) == expect1
&&
//Incorrect cast with dynamic_pointer_cast
boost::get_pointer(boost::dynamic_pointer_cast<derived_derived>( std::move(smart2) )) == expect2;
}
#endif
template <class BasePtr>
bool check_static_moving_pointer_cast(std::function<BasePtr()> f)
{
BasePtr smart = f();
base2 *expect = static_cast<base2*>(static_cast<derived*>(boost::get_pointer(smart)));
return
//Cast base -> derived -> base2 using static_pointer_cast
boost::get_pointer(
boost::static_pointer_cast<base2>(
boost::static_pointer_cast<derived>( std::move(smart) ))) ==
//Now the same with static_cast
expect;
}
template <class BasePtr>
bool check_const_moving_pointer_cast(std::function<BasePtr()> f)
{
BasePtr smart = f();
const base *expect = const_cast<const base*>(const_cast<base*>(boost::get_pointer(smart)));
return
//Unconst and const again using const_pointer_cast
boost::get_pointer(
boost::const_pointer_cast<const base>
(boost::const_pointer_cast<base>( std::move(smart) ))) ==
//Now the same with const_cast
expect;
}
template <class BasePtr>
void check_all_moving_casts(std::function<BasePtr()> f) {
#if !defined( BOOST_NO_RTTI )
BOOST_TEST( check_dynamic_moving_pointer_cast( f ) );
#endif
BOOST_TEST( check_static_moving_pointer_cast( f ) );
BOOST_TEST( check_const_moving_pointer_cast( f ) );
}
}
int main()
{
std::shared_ptr<base> std_shared(new derived);
boost::shared_ptr<base> boost_shared(new derived);
base *plain = boost_shared.get();
// plain & boost::shared_ptr moving pointer_cast checks; there
// is no specific handleing for those types at the moment; this
// test just makes sure they won't break when std::move() is used
// in generic code
check_all_moving_casts<boost::shared_ptr<base>>([&boost_shared]() {
return boost_shared;
});
check_all_moving_casts<base*>([plain]() {
return plain;
});
// std::shared_ptr casts
check_all_copy_casts(std_shared);
check_all_moving_casts<std::shared_ptr<base>>([&std_shared]() {
return std_shared;
});
// std::unique_ptr casts
check_all_moving_casts<std::unique_ptr<base>>([]() {
return std::unique_ptr<base>(new derived);
});
return boost::report_errors();
}
#endif
|