警告 C26431

表达式“expr”的类型已经是 gsl::not_null。 不要测试它是否为空 (f.23)

C++ Core GuidelinesF.23:使用 not_null<T> 指示“null”不是有效值

指南支持库中的标记类型 gsl::not_null 用于清楚地指示绝不为空指针的值。 如果假设在运行时不成立,则会导致硬故障。 因此,显然,如果表达式计算结果为 gsl::not_null 类型的结果,则无需检查 null。

备注

由于 gsl::not_null 本身是一个瘦指针包装器类,因此该规则实际上跟踪临时变量,这些变量保存从调用到重载转换运算符的结果(该变量返回包含的指针对象)。 此类逻辑使此规则适用于涉及变量的表达式,最终具有 gsl::not_null 类型的结果。 但它当前跳过包含返回 gsl::not_null 的函数调用的表达式。

当前空检查的启发式检测以下上下文:

  • 分支条件中的符号表达式,例如 if (p) { ... }
  • 非按位逻辑操作;
  • 比较运算,其中一个操作数是计算结果为零的常量表达式。

代码分析名称:DONT_TEST_NOTNULL

示例

不必要的 null 检查显示可疑逻辑:

class type {
public:
    template<class T> bool is() const;
    template<class T> gsl::not_null<const T*> as() const;
    //...
};

class alias_type : public type {
public:
    gsl::not_null<const type*> get_underlying_type() const;
    gsl::not_null<const type*> get_root_type() const
    {
        const auto ut = get_underlying_type();
        if (ut)                                     // C26431
        {
            const auto uat = ut->as<alias_type>();
            if (uat)                                // C26431, also incorrect use of API!
                return uat->get_root_type();

            return ut;
        }

        return this;                                // Alias to nothing? Actually, dead code!
    }
    //...
};

不必要的空检查揭示了有问题的逻辑,已返工:

    //...
    gsl::not_null<const type*> get_root_type() const
    {
        const auto ut = get_underlying_type();
        if (ut->is<alias_type>())
            return ut->as<alias_type>()->get_root_type();

        return ut;
    }
    //...