exponenta event banner

MISRA C++: 2008 Правило 14-5-1

Универсальная функция, не являющаяся членом, должна объявляться только в пространстве имен, которое не является ассоциированным пространством имен

Описание

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

Универсальная функция, не являющаяся членом, должна объявляться только в пространстве имен, которое не является ассоциированным пространством имен.

Объяснение

Это правило запрещает размещение универсальных функций в том же пространстве имен, что и объявления типа класса (struct), типа перечисления или типа объединения. Если в качестве параметров шаблона используются типы class, enum или union, наличие общих функций в том же пространстве имен может привести к неожиданному разрешению вызовов. Размещайте универсальные функции только в пространствах имен, которые не могут быть связаны с классом, перечислением или типом объединения.

Рассмотрим пространство имен NS который объединяет класс B и общая форма operator==:

namespace NS {
   class B {};
   template <typename T> bool operator==(T, std::int32_t);
}
Если используется класс B в качестве параметра шаблона для другого общего класса, такого как этот класс шаблона A:
template <typename T> class A {
    public:
      bool operator==(std::int64_t);
}

template class A<NS::B>;
все пространство имен NS используется для разрешения перегрузки при операторах класса A называются. Например, если вы звоните operator== с int32_t аргумент, дженерик operator== в пространстве имен NS с int32_t используется вместо параметра operator== в исходном классе шаблона A с int64_t параметр. Вы или другой разработчик или рецензент кода могут ожидать, что вызов оператора решит operator== в исходном классе шаблона A.

Внедрение Polyspace

Для каждой универсальной функции средство проверки правил определяет, содержит ли пространство имен объявления типов классов, типов перечислений или типов объединения. Если такое объявление найдено, средство проверки помечает нарушение правил на самом операторе.

Средство проверки также помечает универсальные функции, определенные в глобальном пространстве имен, если глобальное пространство имен также имеет объявления класса, перечисления или объединения.

Поиск неисправностей

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

Примеры

развернуть все

#include <cstdint>

template <typename T> class Pair {
    std::int32_t item1;
    std::int32_t item2;
    public:
      bool operator==(std::int64_t ItemToCompare);
      bool areItemsEqual(std::int32_t itemValue) {
          return (*this == itemValue);
      }
};

namespace Operations {
    class Data {};
    template <typename T> bool operator==(T, std::int32_t); //Noncompliant
}

namespace Checks {
    bool checkConsistency();
    template <typename T> bool operator==(T, std::int32_t); //Compliant
}

template class Pair<Operations::Data>;

В этом примере пространство имен Operations нарушает правило, поскольку оно содержит тип класса Data рядом с родовым operator==. Пространство имен Checks не нарушает правило, поскольку единственное другое объявление в пространстве имен, кроме общего operator==, является объявлением функции.

В методе areItemsEqual в template class Pair<Operations::Data>, == операция вызывает generic operator== метод в Operations пространство имен. Вызов разрешен для этого operator== метод, основанный на типе данных аргумента (std_int32_t). Этот метод лучше соответствует по сравнению с operator== метод в исходном классе шаблона Pair.

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

Группа: Шаблоны
Категория: Обязательно
Представлен в R2020b