如何投射到私人派生的儿童类型?

时间:2016-07-31 08:14:51

标签: c++ inheritance private-inheritance

以下是尝试使用修改后的语义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)抱怨无效的强制转换。为什么它不起作用,我应该怎么做而不是这个演员?

2 个答案:

答案 0 :(得分:3)

您会看到此编译器错误消息,因为reinterpret_cast无法通过私有继承进行强制转换。请检查以下主题:difference between c++ castsconversion which may be handled by c-style cast only

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

答案 1 :(得分:0)

我建议你的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构造使您的类型兼容。