メインコンテンツ

AUTOSAR C++14 Rule A8-5-4

If a class has a user-declared constructor that takes a parameter of type std::initializer_list, then it shall be the only constructor apart from special member function constructors

R2021a 以降

説明

ルール定義

If a class has a user-declared constructor that takes a parameter of type std::initializer_list, then it shall be the only constructor apart from special member function constructors.

根拠

クラスに std::initializer_list 型のパラメーターを取るコンストラクターと、パラメーターを

classType obj {0,1}
のように中かっこで初期化する別のコンストラクターが含まれている場合、2 つのコンストラクターのどちらが呼び出されるかに関して混乱が生じる可能性があります。コンパイラは std::initializer_list パラメーターを使用するコンストラクターを優先しますが、開発者は別の想定をする可能性があります。

Polyspace 実装

チェッカーは、第 1 パラメーターが std::initializer_list 型であるコンストラクターを含み、別のコンストラクター (特殊なメンバー関数コンストラクターを除く) も含まれているクラス定義にフラグを設定します。ルール違反に続けて、std::initializer_list コンストラクターとの混同を生じさせる可能性がある、他のコンストラクターの場所を指すイベントが示されます。

このルールに違反しない std::initializer_list パラメーターのコンストラクターがあるクラス定義には、既定のコピー コンストラクターと移動コンストラクター (およびコピー代入演算子と移動代入演算子) のみが含まれています。パラメーターを持つ第 2 のコンストラクターを避けられない場合は、このルール違反を正当化できます。この場合、リストを使用する初期化で次のような構文を使用します。

classType obj ({0,1})
このようにすると、std::initializer_list パラメーターのコンストラクターが呼び出されることが明確になります。他のコンストラクターでの初期化では次のような構文を使用します。
classType obj (0,1)
両方の呼び出しはルール A8-5-2 への例外です。一般に () を使用した初期化にはフラグが設定されますが、このような std::initializer_list パラメーターのコンストラクターと他のコンストラクターを共に使用するクラスの初期化は許可されます。

トラブルシューティング

ルール違反が想定されるものの、Polyspace® から報告されない場合は、コーディング規約違反が想定どおりに表示されない理由の診断を参照してください。

すべて展開する

#include <cstdint>
#include <initializer_list>
#include <vector>

class entrySizes {                  //Noncompliant
    public:
       entrySizes()=default;
       entrySizes(std::size_t aCurrentSize, std::size_t aLastSize): 
              currentSize{aCurrentSize}, lastSize{aLastSize} {}
       entrySizes(std::initializer_list<std::size_t> sampleEntry): 
              currentSize{sampleEntry.size()}, lastSize{sampleEntry.size()} {}
    private:
       std::size_t currentSize;
       std::size_t lastSize;
};

class recordSizes {                 //Compliant
    public:
       recordSizes()=default;
       recordSizes(std::initializer_list<std::size_t> sampleRecord): 
              currentSize{sampleRecord.size()}, lastSize{sampleRecord.size()} {}
    private:
       std::size_t currentSize;
       std::size_t lastSize;
};


void createEntry() {
    entrySizes defaultEntrySize{};
    entrySizes stdEntrySize{0,1}; 
       //Calls entrySizes(std::initializer_list<std::size_t> ), 
       //but developer might expect otherwise
    entrySizes expectedEntrySize({0,1}); 
       //Calls entrySizes(std::initializer_list<std::size_t> ), 
       //but developer might expect otherwise
    entrySizes typicalEntrySize(1,1); 
        //Calls entrySizes(std::size_t, std::size_t)
}

void createRecord() {
    recordSizes defaultRecordSize{};
    recordSizes stdRecordSize{0,1}; 
       //Calls recordSizes(std::initializer_list<std::size_t> )
}

この例では、クラス entrySizes に 2 つのユーザー定義コンストラクターが含まれていて、1 つは std::initialize_list パラメーターを使用し、もう 1 つは 2 つの size_t パラメーターを使用しています。2 つのコンストラクターが存在することは、関数 createEntry に示すように開発者を混乱させる可能性があります。現在のクラス定義を維持してルール違反を正当化する場合について、関数 createEntry では std::initialize_list パラメーターのコンストラクターを呼び出すためのより明確な方法も示しています。

クラス recordSizes はこのルールに違反しません。既定のコンストラクターと std::initialize_list パラメーターを持つコンストラクター以外の別のコンストラクターは含まれていないからです。

チェック情報

グループ: 宣言子
カテゴリ: Advisory、Automated

バージョン履歴

R2021a で導入