std::static_pointer_cast, std::dynamic_pointer_cast, std::const_pointer_cast, std::reinterpret_pointer_cast
| ヘッダ <memory> で定義
|
||
template< class T, class U > std::shared_ptr<T> static_pointer_cast( const std::shared_ptr<U>& r ) noexcept; |
(1) | (C++11以上) |
template< class T, class U > std::shared_ptr<T> static_pointer_cast( std::shared_ptr<U>&& r ) noexcept; |
(2) | (C++20以上) |
template< class T, class U > std::shared_ptr<T> dynamic_pointer_cast( const std::shared_ptr<U>& r ) noexcept; |
(3) | (C++11以上) |
template< class T, class U > std::shared_ptr<T> dynamic_pointer_cast( std::shared_ptr<U>&& r ) noexcept; |
(4) | (C++20以上) |
template< class T, class U > std::shared_ptr<T> const_pointer_cast( const std::shared_ptr<U>& r ) noexcept; |
(5) | (C++11以上) |
template< class T, class U > std::shared_ptr<T> const_pointer_cast( std::shared_ptr<U>&& r ) noexcept; |
(6) | (C++20以上) |
template< class T, class U > std::shared_ptr<T> reinterpret_pointer_cast( const std::shared_ptr<U>& r ) noexcept; |
(7) | (C++17以上) |
template< class T, class U > std::shared_ptr<T> reinterpret_pointer_cast( std::shared_ptr<U>&& r ) noexcept; |
(8) | (C++20以上) |
r の格納されているポインタからキャスト式を使用して取得したポインタを格納する新しい std::shared_ptr のインスタンスを作成します。
r が空であれば、新しい shared_ptr も空になります (格納されるポインタがヌルになるとは限りません)。 そうでなければ、新しい shared_ptr は r の初期値と所有権を共有します。 ただし、 dynamic_pointer_cast によって行われる dynamic_cast がヌルポインタを返した場合は空になります。
Y を typename std::shared_ptr<T>::element_type とすると、結果の std::shared_ptr に格納されるポインタはそれぞれ以下を評価することによって取得されます。
static_cast<Y*>(r.get())dynamic_cast<Y*>(r.get()) (dynamic_cast の結果がヌルポインタ値の場合、返される shared_ptr は空になります)const_cast<Y*>(r.get())reinterpret_cast<Y*>(r.get())U* から T* への対応するキャストが well-formed でなければ、これらの関数の動作は未定義です。
static_cast<T*>((U*)nullptr) が well-formed でなければ、動作は未定義です。dynamic_cast<T*>((U*)nullptr) が well-formed でなければ、動作は未定義です。const_cast<T*>((U*)nullptr) が well-formed でなければ、動作は未定義です。reinterpret_cast<T*>((U*)nullptr) が well-formed でなければ、動作は未定義です。|
右辺値オーバーロード (2,4,6,8) の呼び出しの後、 |
(C++20以上) |
引数
| r | - | 変換するポインタ |
ノート
式 std::shared_ptr<T>(static_cast<T*>(r.get()))、std::shared_ptr<T>(dynamic_cast<T*>(r.get())) および std::shared_ptr<T>(const_cast<T*>(r.get())) も同じ効果を持つように見えるかもしれませんが、これらはすべて、同じオブジェクトの delete を2回試みることによる未定義動作になりがちです。
実装例
| 1つめのバージョン |
|---|
template< class T, class U >
std::shared_ptr<T> static_pointer_cast( const std::shared_ptr<U>& r ) noexcept
{
auto p = static_cast<typename std::shared_ptr<T>::element_type*>(r.get());
return std::shared_ptr<T>(r, p);
}
|
| 2つめのバージョン |
template< class T, class U >
std::shared_ptr<T> dynamic_pointer_cast( const std::shared_ptr<U>& r ) noexcept
{
if (auto p = dynamic_cast<typename std::shared_ptr<T>::element_type*>(r.get())) {
return std::shared_ptr<T>(r, p);
} else {
return std::shared_ptr<T>();
}
}
|
| 3つめのバージョン |
template< class T, class U >
std::shared_ptr<T> const_pointer_cast( const std::shared_ptr<U>& r ) noexcept
{
auto p = const_cast<typename std::shared_ptr<T>::element_type*>(r.get());
return std::shared_ptr<T>(r, p);
}
|
| 4つめのバージョン |
template< class T, class U >
std::shared_ptr<T> reinterpret_pointer_cast( const std::shared_ptr<U>& r ) noexcept
{
auto p = reinterpret_cast<typename std::shared_ptr<T>::element_type*>(r.get());
return std::shared_ptr<T>(r, p);
}
|
例
#include <iostream>
#include <memory>
struct Base
{
int a;
virtual void f() const { std::cout << "I am base!\n";}
virtual ~Base(){}
};
struct Derived : Base
{
void f() const override
{ std::cout << "I am derived!\n"; }
~Derived(){}
};
int main(){
auto basePtr = std::make_shared<Base>();
std::cout << "Base pointer says: ";
basePtr->f();
auto derivedPtr = std::make_shared<Derived>();
std::cout << "Derived pointer says: ";
derivedPtr->f();
// static_pointer_cast to go up class hierarchy
basePtr = std::static_pointer_cast<Base>(derivedPtr);
std::cout << "Base pointer to derived says: ";
basePtr->f();
// dynamic_pointer_cast to go down/across class hierarchy
auto downcastedPtr = std::dynamic_pointer_cast<Derived>(basePtr);
if(downcastedPtr)
{
std::cout << "Downcasted pointer says: ";
downcastedPtr->f();
}
// All pointers to derived share ownership
std::cout << "Pointers to underlying derived: "
<< derivedPtr.use_count()
<< "\n";
}
出力:
Base pointer says: I am base!
Derived pointer says: I am derived!
Base pointer to derived says: I am derived!
Downcasted pointer says: I am derived!
Pointers to underlying derived: 3
関連項目
新しい shared_ptr を構築します (パブリックメンバ関数) |