• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1////
2Copyright 2017 Peter Dimov
3
4Distributed under the Boost Software License, Version 1.0.
5
6See accompanying file LICENSE_1_0.txt or copy at
7http://www.boost.org/LICENSE_1_0.txt
8////
9
10[#pointer_cast]
11# Generic Pointer Casts
12:toc:
13:toc-title:
14:idprefix: pointer_cast_
15
16## Description
17
18The pointer cast function templates (`static_pointer_cast`,
19`dynamic_pointer_cast`, `const_pointer_cast`, and `reinterpret_pointer_cast`)
20provide a way to write generic pointer castings for raw pointers,
21`std::shared_ptr` and `std::unique_ptr`.
22
23There is test and example code in
24link:../../test/pointer_cast_test.cpp[pointer_cast_test.cpp]
25
26## Rationale
27
28Boost smart pointers usually overload those functions to provide a mechanism
29to emulate pointers casts. For example, `shared_ptr<T>` implements a static
30pointer cast this way:
31
32```
33template<class T, class U>
34  shared_ptr<T> static_pointer_cast(const shared_ptr<U>& p);
35```
36
37Pointer cast functions templates are overloads of `static_pointer_cast`,
38`dynamic_pointer_cast`, `const_pointer_cast`, and `reinterpret_pointer_cast`
39for raw pointers, `std::shared_ptr` and `std::unique_ptr`. This way when
40developing pointer type independent classes, for example, memory managers or
41shared memory compatible classes, the same code can be used for raw and smart
42pointers.
43
44## Synopsis
45
46The generic pointer casts are defined in `<boost/pointer_cast.hpp>`.
47
48```
49namespace boost {
50  template<class T, class U> T* static_pointer_cast(U* p) noexcept;
51  template<class T, class U> T* dynamic_pointer_cast(U* p) noexcept;
52  template<class T, class U> T* const_pointer_cast(U* p) noexcept;
53  template<class T, class U> T* reinterpret_pointer_cast(U* p) noexcept;
54
55  template<class T, class U> std::shared_ptr<T>
56    static_pointer_cast(const std::shared_ptr<U>& p) noexcept;
57  template<class T, class U> std::shared_ptr<T>
58    dynamic_pointer_cast(const std::shared_ptr<U>& p) noexcept;
59  template<class T, class U> std::shared_ptr<T>
60    const_pointer_cast(const std::shared_ptr<U>& p) noexcept;
61  template<class T, class U> std::shared_ptr<T>
62    reinterpret_pointer_cast(const std::shared_ptr<U>& p) noexcept;
63
64  template<class T, class U> std::unique_ptr<T>
65    static_pointer_cast(std::unique_ptr<U>&& p) noexcept;
66  template<class T, class U> std::unique_ptr<T>
67    dynamic_pointer_cast(std::unique_ptr<U>&& p) noexcept;
68  template<class T, class U> std::unique_ptr<T>
69    const_pointer_cast(std::unique_ptr<U>&& p) noexcept;
70  template<class T, class U> std::unique_ptr<T>
71    reinterpret_pointer_cast(std::unique_ptr<U>&& p) noexcept;
72}
73```
74
75## Free Functions
76
77### static_pointer_cast
78```
79template<class T, class U> T* static_pointer_cast(U* p) noexcept;
80```
81[none]
82* {blank}
83+
84Returns:: `static_cast<T*>(p)`
85
86```
87template<class T, class U> std::shared_ptr<T>
88  static_pointer_cast(const std::shared_ptr<U>& p) noexcept;
89```
90[none]
91* {blank}
92+
93Returns:: `std::static_pointer_cast<T>(p)`
94
95```
96template<class T, class U> std::unique_ptr<T>
97  static_pointer_cast(std::unique_ptr<U>&& p) noexcept;
98```
99[none]
100* {blank}
101+
102Requires:: The expression `static_cast<T*>((U*)0)` must be well-formed.
103Returns:: `std::unique_ptr<T>(static_cast<typename
104std::unique_ptr<T>::element_type*>(p.release()))`.
105
106CAUTION: The seemingly equivalent expression
107`std::unique_ptr<T>(static_cast<T*>(p.get()))` will eventually result in
108undefined behavior, attempting to delete the same object twice.
109
110### dynamic_pointer_cast
111
112```
113template<class T, class U> T* dynamic_pointer_cast(U* p) noexcept;
114```
115[none]
116* {blank}
117+
118Returns:: `dynamic_cast<T*>(p)`
119
120```
121template<class T, class U> std::shared_ptr<T>
122  dynamic_pointer_cast(const std::shared_ptr<U>& p) noexcept;
123```
124[none]
125* {blank}
126+
127Returns:: `std::dynamic_pointer_cast<T>(p)`
128
129```
130template<class T, class U> std::unique_ptr<T>
131  dynamic_pointer_cast(std::unique_ptr<U>&& p) noexcept;
132```
133[none]
134* {blank}
135+
136Requires::
137* The expression `static_cast<T*>((U*)0)` must be well-formed.
138* `T` must have a virtual destructor.
139Returns::
140* When `dynamic_cast<typename std::unique_ptr<T>::element_type*>(p.get())`
141returns a non-zero value, `std::unique_ptr<T>(dynamic_cast<typename
142std::unique_ptr<T>::element_type*>(p.release()));`.
143* Otherwise, `std::unique_ptr<T>()`.
144
145### const_pointer_cast
146
147```
148template<class T, class U> T* const_pointer_cast(U* p) noexcept;
149```
150[none]
151* {blank}
152+
153Returns:: `const_cast<T*>(p)`
154
155```
156template<class T, class U> std::shared_ptr<T>
157  const_pointer_cast(const std::shared_ptr<U>& p) noexcept;
158```
159[none]
160* {blank}
161+
162Returns:: `std::const_pointer_cast<T>(p)`
163
164```
165template<class T, class U> std::unique_ptr<T>
166  const_pointer_cast(std::unique_ptr<U>&& p) noexcept;
167```
168[none]
169* {blank}
170+
171Requires:: The expression `const_cast<T*>((U*)0)` must be well-formed.
172Returns:: `std::unique_ptr<T>(const_cast<typename
173std::unique_ptr<T>::element_type*>(p.release()))`.
174
175### reinterpret_pointer_cast
176
177```
178template<class T, class U> T* reinterpret_pointer_cast(U* p) noexcept;
179```
180[none]
181* {blank}
182+
183Returns:: `reinterpret_cast<T*>(p)`
184
185```
186template<class T, class U> std::shared_ptr<T>
187  reinterpret_pointer_cast(const std::shared_ptr<U>& p) noexcept;
188```
189[none]
190* {blank}
191+
192Returns:: `std::reinterpret_pointer_cast<T>(p)`
193
194```
195template<class T, class U> std::unique_ptr<T>
196  reinterpret_pointer_cast(std::unique_ptr<U>&& p) noexcept;
197```
198[none]
199* {blank}
200+
201Requires:: The expression `reinterpret_cast<T*>((U*)0)` must be well-formed.
202Returns:: `std::unique_ptr<T>(reinterpret_cast<typename
203std::unique_ptr<T>::element_type*>(p.release()))`.
204
205## Example
206
207The following example demonstrates how the generic pointer casts help us
208create pointer independent code.
209
210```
211#include <boost/pointer_cast.hpp>
212#include <boost/shared_ptr.hpp>
213
214class base {
215public:
216  virtual ~base() { }
217};
218
219class derived : public base { };
220
221template<class Ptr>
222void check_if_it_is_derived(const Ptr& ptr)
223{
224  assert(boost::dynamic_pointer_cast<derived>(ptr) != 0);
225}
226
227int main()
228{
229  base* ptr = new derived;
230  boost::shared_ptr<base> sptr(new derived);
231
232  check_if_it_is_derived(ptr);
233  check_if_it_is_derived(sptr);
234
235  delete ptr;
236}
237```
238