Main Content

MISRA C++:2008 Rule 14-5-1

A non-member generic function shall only be declared in a namespace that is not an associated namespace

Since R2020b

Description

Rule Definition

A non-member generic function shall only be declared in a namespace that is not an associated namespace.

Rationale

This rule forbids placing generic functions in the same namespace as class (struct) type, enum type, or union type declarations. If the class, enum or union types are used as template parameters, the presence of generic functions in the same namespace can cause unexpected call resolutions. Place generic functions only in namespaces that cannot be associated with a class, enum or union type.

Consider the namespace NS that combines a class B and a generic form of operator==:

namespace NS {
   class B {};
   template <typename T> bool operator==(T, std::int32_t);
}
If you use class B as a template parameter for another generic class, such as this template class A:
template <typename T> class A {
    public:
      bool operator==(std::int64_t);
}

template class A<NS::B>;
the entire namespace NS is used for overload resolution when operators of class A are called. For instance, if you call operator== with an int32_t argument, the generic operator== in the namespace NS with an int32_t parameter is used instead of the operator== in the original template class A with an int64_t parameter. You or another developer or code reviewer might expect the operator call to resolve to the operator== in the original template class A.

Polyspace Implementation

For each generic function, the rule checker determines if the containing namespace also contains declarations of class types, enum types, or union types. If such a declaration is found, the checker flags a rule violation on the operator itself.

The checker also flags generic functions defined in the global namespace if the global namespace also has class, enum or union declarations.

Troubleshooting

If you expect a rule violation but Polyspace® does not report it, see Diagnose Why Coding Standard Violations Do Not Appear as Expected.

Examples

expand all

#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>;

In this example, the namespace Operations violates the rule because it contains the class type Data alongside the generic operator==. The namespace Checks does not violate the rule because the only other declaration in the namespace, besides the generic operator==, is a function declaration.

In the method areItemsEqual in template class Pair<Operations::Data>, the == operation invokes the generic operator== method in the Operations namespace. The invocation resolves to this operator== method based on the argument data type (std_int32_t). This method is a better match compared to the operator== method in the original template class Pair.

Check Information

Group: Templates
Category: Required

Version History

Introduced in R2020b