exponenta event banner

Правило AUTOSAR C++ 14 A8-5-4

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

Описание

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

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

Объяснение

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

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

Внедрение Polyspace

Средство проверки помечает определения классов, содержащие конструктор, первый параметр которого имеет тип 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