AUTOSAR C++14 Rule A8-5-4

Если у класса есть объявленный пользователем конструктор, который принимает параметр типа std::initializer_list, то он должен быть единственным конструктором, кроме конструкторов функций специальных представителей

Описание

Определение правила

Если класс имеет объявленный пользователем конструктор, который принимает параметр типа std::initializer_list, то он должен быть единственным конструктором, кроме конструкторов функций специальных представителей.

Объяснение

Если класс содержит конструктор, который принимает параметр типа std::initializer_list и другой конструктор с параметрами, скрепленными инициализациями, такими как:

classType obj {0,1}
Может привести к путанице в отношении того, какой из двух конструкторов вызывается. Компиляторы предпочитают конструктор с std::initializer_list параметр, но разработчики могут ожидать в противном случае.

Реализация Polyspace

Checker помечает определения классов, которые содержат конструктор, первый параметр которого имеет тип std::initializer_list и также содержит другой конструктор (исключая конструкторы функций специальных представителей). За нарушением правил следуют события, которые указывают на расположение других конструкторов, которые могут привести к путанице со std::initializer_list конструктор.

Определение класса со std::initializer_list-параметр конструктор, который не нарушает это правило имеет только по умолчанию, копировать и перемещать конструкторы (и копировать и перемещать операторов назначения). Если вы не можете избежать второго конструктора с параметрами, можно обосновать это нарушение правила. В этом случае для инициализации со списком используйте такой синтаксис, как:

classType obj ({0,1})
так что ясно, что std::initializer_list-параметровый конструктор вызывается. Для инициализации с другими конструкторами используйте синтаксис, такой как:
classType obj (0,1)
Оба вызова являются исключениями из правила A8-5-2, которое обычно помечает инициализацию (), но позволяет такие инициализации для классов со смесью std::initializer_list-параметровый конструктор и другие конструкторы.

Поиск и устранение проблем

Если вы ожидаете нарушения правил, но не видите его, обратитесь к разделу «Стандартные нарушения кодирования не отображаются».

Примеры

расширить все

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

//Noncompliant class definition
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;
};

//Compliant class definition
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;
};

//Calls to constructors from noncompliant class
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)
}

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

В этом примере класс entrySizes содержит два пользовательских конструктора, один со std::initialize_list параметр и второй с двумя size_t параметры. Наличие двух конструкторов может привести к путанице разработчика, как показано на createEntry функция. В случае, если вы хотите сохранить текущее определение класса и обосновать нарушение правила, createEntry функция также показывает более чистый способ вызова std::initialize_list-параметр конструктор.

Класс recordSizes не нарушает правило, поскольку не содержит другого конструктора, кроме конструктора по умолчанию и конструктора со std::initialize_list параметр.

Проверяйте информацию

Группа: Деклараторы
Категория: Консультационные, Автоматизированные
Введенный в R2021a