MISRA C++:2008 Rule 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>, а == операция вызывает типовой operator== метод в Operations пространство имен. Вызов разрешается к этому operator== метод, основанный на типе данных аргумента (std_int32_t). Этот метод является лучшим по сравнению с operator== метод в исходном классе шаблона Pair.

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

Группа: Шаблоны
Категория: Требуемая
Введенный в R2020b