Main Content

AUTOSAR C++14 Rule A14-5-3

A non-member generic operator shall only be declared in a namespace that does not contain class (struct) type, enum type or union type declarations

Description

Rule Definition

A non-member generic operator shall only be declared in a namespace that does not contain class (struct) type, enum type or union type declarations.

Rationale

This rule forbids placing generic operators 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 operators in the same namespace can cause unexpected call resolutions.

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 operator, 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 operators 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: Advisory, Automated