Как можно уменьшить std :: shared_ptr? - PullRequest
56 голосов
/ 23 июля 2011

Рассмотрим:

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.
    }
}

(Обратите внимание, что я не могу просто сделать std::shared_ptr<ChildOne>(static_cast<ChildOne*>(ptr.get())), потому что тогда счетчики ссылок не будут разделены между двумя shared_ptr с)

Ответы [ 3 ]

83 голосов
/ 23 июля 2011

Это должно работать:

if (ptr->IsChildOne())
{
    SomeClientExpectingAChildOne(std::static_pointer_cast<ChildOne>(ptr));
}
34 голосов
/ 23 июля 2011

shared_ptr эквивалент static_cast равен static_pointer_cast, а shared_ptr эквивалент dynamic_cast равен dynamic_pointer_cast.

19 голосов
/ 28 апреля 2016

Начиная с C ++ 11, §20.10.2.2.9 ( [util.smartptr.shared.cast] ) стандарта C ++ определяет эквиваленты 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>, в противном случае возвращается указатель w, разделяющий владение с r, где w.get() == static_cast<T *>(r.get()) и w.use_count() == r.use_count().

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, за исключением того, что вместо static_cast используется const_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 (принятый в Основы библиотек TS в феврале 2014 года ) также предложил 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 для поддержки массивов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...