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

Clang-tidy针对父类已删特殊成员函数的子类报‘五法则’警告

Clang-tidy特殊成员函数警告问题解析

问题场景

用户运行Clang-tidy检查以下C++代码:

struct Base {
    Base() = default;
    virtual ~Base() = default;
    Base(const Base&) = delete;
    Base& operator=(const Base&) = delete;
    Base(Base&&) = delete; // not really needed
    Base& operator=(Base&&) = delete; // not really needed
};

template<typename T>
struct Crtp : Base {};

struct Derived : Crtp<Derived> {
    ~Derived() noexcept override { /*...*/ }
};

触发警告:

Class 'Derived' defines a non-default destructor but does not define a copy constructor, a copy assignment operator, a move constructor or a move assignment operator [cppcoreguidelines-special-member-functions,hicpp-special-member-functions]

用户疑惑:基类Base已删除所有拷贝/移动相关的特殊成员函数,为何仍触发警告?即使配置了以下Clang-tidy选项也无效:

CheckOptions: [
  { key: cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor, value: true },
  { key: hicpp-special-member-functions.AllowSoleDefaultDtor, value: true },
  { key: cppcoreguidelines-special-member-functions.AllowMissingMoveFunctions, value: true },
  { key: hicpp-special-member-functions.AllowMissingMoveFunctions, value: true },
  { key: cppcoreguidelines-special-member-functions.AllowMissingMoveFunctionsWhenCopyIsDeleted, value: true },
  { key: hicpp-special-member-functions.AllowMissingMoveFunctionsWhenCopyIsDeleted, value: true }
]

原因解析

这不是Clang-tidy的bug,而是对检查规则的认知遗漏,核心原因如下:

  1. 检查的针对性:cppcoreguidelines-special-member-functions(及对应的hicpp规则)的检查逻辑是针对当前类(Derived)自身的特殊成员函数声明情况,而非继承自基类的状态。即使基类已删除拷贝/移动函数,只要当前类定义了非默认析构函数,却没有显式声明(包括默认或删除)其他特殊成员,就会触发警告——编译器因基类原因隐式删除Derived的拷贝/移动函数,并不会被Clang-tidy自动识别为符合规则。

  2. 配置选项不生效的原因:用户配置的AllowMissingMoveFunctionsWhenCopyIsDeleted等选项,要求当前类显式删除拷贝函数,才能忽略移动函数的缺失。但Derived的拷贝函数是因基类的拷贝函数被删除而隐式删除的,并非自身显式声明删除,因此不满足选项的触发条件。另外,AllowSoleDefaultDtor选项仅适用于当前类只有默认析构函数的场景,而Derived的析构是自定义实现的,自然也不生效。

解决方法

有两种可行的解决方案:

  • 显式声明删除特殊成员:在Derived类中显式删除拷贝/移动相关函数,让Clang-tidy明确感知到你对这些成员的处理意图:

    struct Derived : Crtp<Derived> {
        ~Derived() noexcept override { /*...*/ }
        Derived(const Derived&) = delete;
        Derived& operator=(const Derived&) = delete;
        Derived(Derived&&) = delete;
        Derived& operator=(Derived&&) = delete;
    };
    
  • 调整Clang-tidy配置:如果使用的Clang-tidy版本支持AllowImplicitlyDeletedSpecialMembers选项(部分新版本已添加),可以添加该配置来允许因基类原因隐式删除特殊成员的情况:

    CheckOptions: [
      { key: cppcoreguidelines-special-member-functions.AllowImplicitlyDeletedSpecialMembers, value: true },
      { key: hicpp-special-member-functions.AllowImplicitlyDeletedSpecialMembers, value: true }
    ]
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 21:20:51