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

如何禁止派生类场景下临时shared_ptr向weak_ptr转换

适配继承场景的weak_ptr防临时构造方案

问题背景

此前针对具体类型的防临时shared_ptr构造weak_ptr的方案,在涉及类继承的场景下会失效。
当前场景定义:

  • 存在继承关系的两个类Foo和IFoo,其中class Foo: public IFoo
  • 存在业务函数void use_weak_ptr(std::weak_ptr<IFoo>)
    需要确保编译阶段满足以下规则:
  • 传入左值shared_ptr时正常编译:
auto shared = std::make_shared<Foo>();
use_weak_ptr(shared);
  • 传入临时(右值)shared_ptr时编译失败:
use_weak_ptr(std::make_shared<Foo>());

实现方案

原有方案失效的核心原因是:之前仅删除了接受std::shared_ptr<IFoo>&&的重载,当传入派生类Foo的右值shared_ptr时,隐式转换优先级会让其绕过该删除重载,直接构造std::weak_ptr<IFoo>传入函数。
只需要补充一个模板化的右值删除重载,拦截所有类型的右值shared_ptr即可,完整代码如下:

#include <memory>

class IFoo {};
class Foo : public IFoo {};

// 业务主函数,接受weak_ptr执行逻辑
void use_weak_ptr(std::weak_ptr<IFoo>) {
    // 业务逻辑实现
}

// 拦截所有右值shared_ptr,禁止从临时shared_ptr构造weak_ptr传入
template<typename T>
void use_weak_ptr(std::shared_ptr<T>&&) = delete;

int main() {
    // 符合预期:正常编译
    auto shared = std::make_shared<Foo>();
    use_weak_ptr(shared);

    // 符合预期:编译报错,调用了已删除的重载
    // use_weak_ptr(std::make_shared<Foo>());
    return 0;
}

原理说明

  • 当传入左值shared_ptr时(无论类型是std::shared_ptr<IFoo>还是任意派生类的std::shared_ptr<T>),右值引用重载无法绑定左值,不会参与重载匹配,参数会正常隐式转换为std::weak_ptr<IFoo>调用业务主函数,逻辑正常。
  • 当传入右值shared_ptr时(包括std::make_shared返回的临时对象),模板重载可以直接推导出参数类型,无需任何类型转换,匹配优先级高于需要用户自定义转换的shared_ptr转weak_ptr路径,会直接匹配到已删除的重载,触发编译错误。该逻辑对所有继承层级的派生类都生效,不存在漏拦截问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 03:51:24