如何强制转换为私有派生的子类型

How to cast to privately derived child type?

本文关键字:派生 类型 何强制 转换      更新时间:2023-10-16

以下是用修改后的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)抱怨一个无效的强制转换。为什么它不起作用?我应该做什么来代替这个演员阵容?

您会看到此编译器错误消息,因为reinterpret_cast无法通过私有继承进行强制转换。请检查此主题的以下主题:c++转换之间的差异,转换可能仅由c样式转换处理。

执行private继承的唯一方法是c样式转换。因此,按照以下方式更改您的示例会使您的示例起作用:

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在这种情况下是安全的。

我建议您的deref_shared_ptr实现一个构造函数,该构造函数接收std::shared_ptr作为参数,因此转换是可能的。现在,您的编译器不知道如何从std::shared_ptr生成deref_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使您的类型兼容。