You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何编写构造函数实现shared_const_ptr<Derived>到shared_const_ptr<Base>的隐式转换

问题:实现shared_const_ptr的派生类隐式转换

我创建了一个继承自std::shared_ptr<const T>的模板类shared_const_ptr,允许持有者通过克隆实例并重置shared_ptr来修改指向的对象。(T可以是可克隆类或具备拷贝构造函数的类,因此modify方法有两种不同定义)。

std::shared_ptr<Base>可以由std::shared_ptr<Derived>实例隐式构造或拷贝,但我的shared_const_ptr类无法实现该功能。请问如何实现这一特性?我推测需要编写一个接受shared_const_ptr<D>类型参数的模板构造函数(其中D是模板类型C的派生类),但不知具体写法。由于shared_ptr可以实现该功能,我认为这是可行的。

附上代码:

template <typename T, typename = int>
struct HasPolymorphicClonage : std::false_type { };
template <typename T>
struct HasPolymorphicClonage <T, decltype(&T::clone, 0)> : std::true_type { };

template<typename C>
class shared_const_ptr : public std::shared_ptr<const C>
{
public :
    shared_const_ptr(const C * c) : std::shared_ptr<const C>(c) {}
    shared_const_ptr() =default;

    // 根据T是否提供clone方法定义modify
    template<typename T1 = C>
    typename std::enable_if_t<HasPolymorphicClonage<T1>::value,C&> modify()
    {
        C * remplacant = (*this)->clone();
        this->std::shared_ptr<const C>::reset(remplacant);
        return *remplacant;
    }

    template<typename T1 = C>
    typename std::enable_if_t<!HasPolymorphicClonage<T1>::value,C&> modify()
    {
        C * remplacant = new C(**this); // 使用拷贝构造函数
        this->std::shared_ptr<const C>::reset(remplacant);
        return *remplacant;
    }

};

解决方案

要实现shared_const_ptr<D>到shared_const_ptr<C>的隐式转换(其中D是C的派生类),只需添加带约束的模板构造函数,利用std::is_base_of确保类型安全,同时复用std::shared_ptr自身的派生类转换逻辑。

修改后的完整代码

#include <memory>
#include <type_traits>

template <typename T, typename = int>
struct HasPolymorphicClonage : std::false_type { };
template <typename T>
struct HasPolymorphicClonage <T, decltype(&T::clone, 0)> : std::true_type { };

template<typename C>
class shared_const_ptr : public std::shared_ptr<const C>
{
public :
    shared_const_ptr(const C * c) : std::shared_ptr<const C>(c) {}
    shared_const_ptr() = default;

    // 支持从shared_const_ptr<D>隐式构造(D是C的派生类)
    template<typename D, typename = std::enable_if_t<std::is_base_of_v<C, D>>>
    shared_const_ptr(const shared_const_ptr<D>& other)
        : std::shared_ptr<const C>(static_cast<const std::shared_ptr<const D>&>(other))
    {
    }

    // 支持从shared_const_ptr<D>隐式赋值(D是C的派生类)
    template<typename D, typename = std::enable_if_t<std::is_base_of_v<C, D>>>
    shared_const_ptr& operator=(const shared_const_ptr<D>& other)
    {
        std::shared_ptr<const C>::operator=(static_cast<const std::shared_ptr<const D>&>(other));
        return *this;
    }

    // 根据T是否提供clone方法定义modify
    template<typename T1 = C>
    typename std::enable_if_t<HasPolymorphicClonage<T1>::value,C&> modify()
    {
        C * remplacant = (*this)->clone();
        this->std::shared_ptr<const C>::reset(remplacant);
        return *remplacant;
    }

    template<typename T1 = C>
    typename std::enable_if_t<!HasPolymorphicClonage<T1>::value,C&> modify()
    {
        C * remplacant = new C(**this); // 使用拷贝构造函数
        this->std::shared_ptr<const C>::reset(remplacant);
        return *remplacant;
    }

};

关键说明

  1. 模板构造函数:通过template<typename D>定义,并用std::enable_if_t<std::is_base_of_v<C, D>>作为默认模板参数,确保只有当D是C的派生类(或相同类型)时,该构造函数才会被启用。
  2. 复用基类逻辑:构造函数内部将shared_const_ptr<D>转换为其基类std::shared_ptr<const D>,再利用std::shared_ptr本身支持的派生到基类的隐式转换,完成std::shared_ptr<const C>的构造。
  3. 赋值运算符重载:同样添加模板赋值运算符,确保赋值操作也支持派生类到基类的隐式转换。

这样修改后,你就可以像使用std::shared_ptr一样,实现shared_const_ptr<Derived>到shared_const_ptr<Base>的隐式构造和赋值了。


内容的提问来源于stack exchange,提问作者Arnaud

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 10:55:04