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

source code of boost/libs/smart_ptr/test/cpp11_pointer_cast_test.cpp