web-dev-qa-db-ja.com

std :: shared_ptrをどのようにダウンキャストしますか?

考慮してください:

_struct SomethingThatsABase
{
    virtual bool IsChildOne() const { return false; }
    virtual bool IsChildTwo() const { return false; }
};

struct ChildOne : public SomethingThatsABase
{
    virtual bool IsChildOne() const { return true; }
};

struct ChildTwo : public SomethingThatsABase
{
    virtual bool IsChildTwo() const { return true; }
};

void SomeClientExpectingAChildOne(std::shared_ptr<ChildOne> const& ptrOne)
{
    //Does stuff
}

void SomeClient(std::shared_ptr<SomethingThatsABase> const& ptr)
{
    if (ptr->IsChildOne())
    {
        SomeClientExpectingAChildOne(ptr); //Oops.
        //Hmm.. can't static_cast here, because we need a `shared_ptr` out of it.
    }
}
_

(参照カウントが2つの_shared_ptr_ s間で共有されないため、単純にstd::shared_ptr<ChildOne>(static_cast<ChildOne*>(ptr.get()))を実行できないことに注意してください)

59
Billy ONeal

これは動作するはずです:

if (ptr->IsChildOne())
{
    SomeClientExpectingAChildOne(std::static_pointer_cast<ChildOne>(ptr));
}
85
mwigdahl

shared_ptrに相当するstatic_caststatic_pointer_cast、 そしてその shared_ptrに相当するdynamic_castdynamic_pointer_cast

34
Joel

C++ 11以降、C++標準の§20.10.2.2.9( [util.smartptr.shared.cast] )は、 _static_cast_、_const_cast_、および_dynamic_cast_の場合、_std::shared_ptr_は次のようになります。

_std::static_pointer_cast_:

_template <class T, class U>
shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r) noexcept;
_

_static_pointer_cast_には、static_cast<T *>(r.get())の整形式が必要です。 rが空の場合は、空の_shared_ptr<T>_が返されます。そうでない場合は、ww.get() == static_cast<T *>(r.get())およびw.use_count() == r.use_count())と所有権を共有するポインターrが返されます。

_std::const_pointer_cast_:

_template <class T, class U>
shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r) noexcept;
_

_const_pointer_cast_には、_static_pointer_cast_の代わりに_const_cast_が使用されることを除いて、_static_cast_と同様の要件とセマンティクスがあります。

_std::dynamic_pointer_cast_:

_template <class T, class U>
shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r) noexcept;
_

_dynamic_pointer_cast_は、dynamic_cast<T *>(r.get())の形式が適切であり、セマンティクスが明確に定義されている必要があるため、少し異なります。 dynamic_cast<T *>(r.get())がゼロ以外の値である場合、所有権をwと共有するポインターrを返します。ここでw.get() == dynamic_cast<T *>(r.get())およびw.use_count() == r.use_count()、そうでない場合は空の_shared_ptr<T>_が返されます。

_std::reinterpret_pointer_cast_:

C++ 17の場合、 N3920 (2014年2月にLibrary Fundamentals TS に採用されました )上記と同様の_std::reinterpret_pointer_cast_も提案しました。これは、reinterpret_cast<T *>((U *) 0)が整形式である必要があるだけで、shared_ptr<T>(r, reinterpret_cast<typename shared_ptr<T>::element_type *>(r.get()))を返します。注N3920は、他の_shared_ptr_キャストの表現を変更し、配列をサポートするように_shared_ptr_を拡張しました。

19
jotik