次の方法で共有


警告 C26431

式 'expr' の型は既に gsl::not_null。 null 値をテストしないでください (f.23)

C++ Core Guidelines: F.23: not_null<T> を使用して、"null" が有効な値ではないことを示します

ガイドライン サポート ライブラリから gsl::not_null マーカーの種類は、null ポインターでない値を明確に示すために使用されます。 実行時に想定が保持されない場合は、ハード エラーが発生します。 したがって、式が gsl::not_null型の結果に評価される場合は、明らかに null をチェックする必要はありません。

解説

gsl::not_null自体はシン ポインター ラッパー クラスであるため、ルールは実際にはオーバーロードされた変換演算子 (包含ポインター オブジェクトを返す) の呼び出しの結果を保持する一時変数を追跡します。 このようなロジックにより、変数を含み、最終的に gsl::not_null 型の結果を持つ式にこの規則が適用されます。 ただし、現在、 gsl::not_nullを返す関数呼び出しを含む式はスキップされます。

null チェックの現在のヒューリスティックでは、次のコンテキストが検出されます。

  • 分岐条件のシンボル式 (例: if (p) { ... };
  • ビットごとではない論理演算
  • 1 つのオペランドが 0 に評価される定数式である比較演算

コード分析名: 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!
    }
    //...
};

不要な null チェックにより、疑わしいロジックが明らかにされ、次の処理が行われます。

    //...
    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;
    }
    //...