名前空間
変種
操作

std::static_pointer_cast, std::dynamic_pointer_cast, std::const_pointer_cast, std::reinterpret_pointer_cast

提供: cppreference.com
< cpp‎ | memory‎ | shared ptr
 
 
ユーティリティライブラリ
汎用ユーティリティ
日付と時間
関数オブジェクト
書式化ライブラリ (C++20)
(C++11)
関係演算子 (C++20で非推奨)
整数比較関数
(C++20)
スワップと型操作
(C++14)
(C++11)
(C++11)
(C++11)
(C++17)
一般的な語彙の型
(C++11)
(C++17)
(C++17)
(C++17)
(C++17)

初等文字列変換
(C++17)
(C++17)
 
動的メモリ管理
スマートポインタ
(C++11)
(C++11)
(C++11)
(C++17未満)
(C++11)
アロケータ
メモリリソース
未初期���記憶域
ガベージコレクションサポート
その他
(C++20)
(C++11)
(C++11)
C のライブラリ
低水準のメモリ管理
 
 
ヘッダ <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_ptrr の初期値と所有権を共有します。 ただし、 dynamic_pointer_cast によって行われる dynamic_cast がヌルポインタを返した場合は空になります。

Ytypename std::shared_ptr<T>::element_type とすると、結果の std::shared_ptr に格納されるポインタはそれぞれ以下を評価することによって取得されます。

1-2) static_cast<Y*>(r.get())
3-4) dynamic_cast<Y*>(r.get()) (dynamic_cast の結果がヌルポインタ値の場合、返される shared_ptr は空になります)
5-6) const_cast<Y*>(r.get())
7-8) reinterpret_cast<Y*>(r.get())

U* から T* への対応するキャストが well-formed でなければ、これらの関数の動作は未定義です。

1-2) static_cast<T*>((U*)nullptr) が well-formed でなければ、動作は未定義です。
3-4) dynamic_cast<T*>((U*)nullptr) が well-formed でなければ、動作は未定義です。
5-6) const_cast<T*>((U*)nullptr) が well-formed でなければ、動作は未定義です。
7-8) reinterpret_cast<T*>((U*)nullptr) が well-formed でなければ、動作は未定義です。

右辺値オーバーロード (2,4,6,8) の呼び出しの後、 r は空となり、 r.get() == nullptr となります。 ただし dynamic_pointer_cast (4) については、 dynamic_cast が失敗した場合は r は変更されません。

(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 を構築します
(パブリックメンバ関数) [edit]