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