C++继承std::shared_ptr的构造函数跨编译器行为差异问题
问题根本原因
这是编译器对C++标准的实现差异导致的问题,其中MSVC的行为属于非标准扩展,GCC/Clang的编译结果符合标准要求。
核心规则说明
- 初始化方式差异
你代码中出错的行是复制初始化场景:
复制初始化要求源类型MyPtr<int> a = std::make_shared<int>();std::shared_ptr<int>到目标类型MyPtr<int>存在合法的隐式转换,而直接初始化MyPtr<int> a(std::make_shared<int>())不存在隐式转换要求,因此在所有编译器下都可以正常编译。 - 继承构造函数的限制
你通过using base::base;确实继承了std::shared_ptr的所有构造函数,包括它的拷贝、移动构造函数。但C++标准明确规定:基类自身的拷贝、移动构造函数被继承到派生类后,不会被视为派生类的转换构造函数,不能用于隐式类型转换场景。
你传入的std::shared_ptr<int>右值刚好匹配基类的移动构造函数签名,因此GCC/Clang认为没有合法的隐式转换路径,抛出转换错误。 - MSVC的非标准行为
MSVC没有实现上述标准限制,允许继承来的基类拷贝/移动构造函数作为派生类的转换构造函数使用,属于编译器的非标准扩展,因此可以编译通过你的代码。
修复方案
如果需要代码跨编译器兼容,只需要手动添加对应的转换构造函数即可:
#include <memory> template <typename T> class MyPtr : public std::shared_ptr<T> { using base = std::shared_ptr<T>; public: using base::operator=; using base::base; // 手动添加隐式转换需要的构造函数 MyPtr(base&& other) noexcept : base(std::move(other)) {} MyPtr(const base& other) : base(other) {} }; int main() { MyPtr<int> a = std::make_shared<int>(); // 所有编译器下均编译通过 }
内容的提问来源于stack exchange,提问作者Fedor
相关产品推荐
相关产品推荐

