Main Content

AUTOSAR C++14 Rule A13-5-4

If two opposite operators are defined, one shall be defined in terms of the other

Since R2022a

Description

Rule Definition

If two opposite operators are defined, one shall be defined in terms of the other.

Rationale

Opposite operators have the same argument and return types but exactly complement each other. For instance, operator== checks if its arguments are equal and operator!= checks for the complementary relation, that is, inequality.

Defining opposite operators in terms of each other makes your code easier to maintain:

  • If you define opposite operators independently of each other, each time you update one operator, you have to remember to update the other. For instance, if you update the definition of operator==. you have to also explicitly update the definition of operator!=.

  • If you define opposite operators in terms of each other, updating only one operator is sufficient since that change implicitly updates the other operator.

Polyspace Implementation

The checker raises a violation if one of the operators in the following pairs is not defined in terms of the other:

  • operator==, operator!=

  • operator<, operator>=

  • operator>, operator<=

The checker flags one of the operators in the pair. The event list below the checker result shows the location of the other operator.

The checker considers two opposite operators as part of a pair only if they have the same argument and return types.

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>

class Info {
    public:
       explicit Info(std::uint32_t x, std::uint32_t y): x(x), y(y) {}
       friend bool operator==(const Info & lhs, const Info & rhs) {
           return ((lhs.x == rhs.x) && (lhs.y == rhs.y));
       }
       friend bool operator!=(const Info & lhs, const Info & rhs) { //Noncompliant
           return ((lhs.x != rhs.x) || (lhs.y != rhs.y));
       }
    private:
       std::uint32_t x;
       std::uint32_t y;
};

class Data {
    public:
       explicit Data(std::uint32_t x, std::uint32_t y): x(x), y(y) {}
       friend bool operator==(const Data & lhs, const Data & rhs) {
           return ((lhs.x == rhs.x) && (lhs.y == rhs.y));
       }
       friend bool operator!=(const Data & lhs, const Data & rhs) { //Compliant
           return !(lhs == rhs);
       }
    private:
       std::uint32_t x;
       std::uint32_t y;
};

In this example, the class Info defines the two opposite operators operator== and operator!= independently of each other. If you add another data member to the class or change to a different definition of equality, you have to explicitly update the definitions of both operators.

The class Data defines the same two operators, but operator!= is defined in terms of operator==. If you add a data member to the class later or change to a different definition of equality, you can change only the operator== operator. The operator!= operator will automatically reflect the change.

Check Information

Group: Overloading
Category: Required, Automated

Version History

Introduced in R2022a