Как привести к частному дочернему типу?

Ниже приведена попытка реализации общего указателя с измененной семантикой operator==:

template <typename T>
struct deref_shared_ptr: private std::shared_ptr<T> {
using Base = std::shared_ptr<T>;
// ... using statements to include functionality from the base.

bool operator==(const deref_shared_ptr rhs) const {
return (**this == *rhs);
}
};

Я борюсь с реализацией эквивалента std::make_shared для этого типа. Это моя попытка:

template< class T, class... Args >
deref_shared_ptr<T> make_deref_shared( Args&&... args ) {
return reinterpret_cast<deref_shared_ptr<T>>(std::make_shared<T>(args...));
}

Это не работает: компилятор (g++ 5.4.0) жалуется на неверный актерский состав. Почему это не работает и что я должен делать вместо этого броска?

0

Решение

Вы видите это сообщение об ошибке компилятора, потому что reinterpret_cast не может делать слепки через частное наследство. Пожалуйста, проверьте следующие темы по этой теме: разница между бросками с ++, преобразование, которое может быть обработано только в стиле c.

Единственный способ пройти через private Наследование — это актёрский стиль. Итак, изменение вашего примера следующим образом заставит ваш пример работать:

template< class T, class... Args >
deref_shared_ptr<T> make_deref_shared(Args&&... args) {
return (deref_shared_ptr<T>)(std::make_shared<T>(args...));
}

Приведение в стиле c небезопасно в общем случае, так как оно может работать некорректно в случаях множественного наследования и некоторых других случаях, но AFAIK в этом случае безопасно.

3

Другие решения

Я предлагаю ваш deref_shared_ptr реализовать конструктор, который получает std::shared_ptr как параметр, так что преобразование будет возможно. Прямо сейчас ваш компилятор не знает, как сделать deref_shared_ptr из std::shared_ptr, Это именно то, чему мы научим ваш компилятор.

Я заметил, что вы добавили кастом operator== правильно сравнить ваш тип с std::shared_ptr, Здесь мы хотим сделать то же самое, но с помощью конструктора. Мы хотим конструктор, который правильно построить с вашим типом с std::shared_ptr!

Конструктор будет выглядеть так:

template<typename T>
struct deref_shared_ptr : private std::shared_ptr<T> {
// An alias to the parent may help msvc with templated parent types
using parent = std::shared_ptr<T>;

// Implement a constructor that takes shared_ptr by copy and move
deref_shared_ptr(const parent& ptr) : parent{ptr} {}
deref_shared_ptr(parent&& ptr) : parent{std::move(ptr)} {}

// stuff...
};

Затем функция make становится тривиальной для реализации:

template<typename T, typename... Args>
deref_shared_ptr<T> make_deref_shared(Args&&... args) {
// Don't forget perfect forwarding here!
return std::make_shared<T>(std::forward<Args>(args)...);
}

РЕДАКТИРОВАТЬ:

В качестве альтернативы, если ваши конструкторы не выполняют никаких операций, вы можете использовать наследующие конструкторы:

template<typename T>
struct deref_shared_ptr : private std::shared_ptr<T> {
using parent = std::shared_ptr<T>;

// Implement constructors
using parent::parent;

// stuff...
};

Это упростит реализацию конструктора и сделает ваш тип совместимым по конструкции с std::shared_ptr,

0

По вопросам рекламы [email protected]