5 Expressions [expr]

5.10 Equality operators [expr.eq]

equality-expression:
    relational-expression
    equality-expression == relational-expression
    equality-expression != relational-expression

The == (equal to) and the != (not equal to) operators group left-to-right. The operands shall have arithmetic, enumeration, pointer, or pointer to member type, or type std::nullptr_t. The operators == and != both yield true or false, i.e., a result of type bool. In each case below, the operands shall have the same type after the specified conversions have been applied.

If at least one of the operands is a pointer, pointer conversions ([conv.ptr]) and qualification conversions ([conv.qual]) are performed on both operands to bring them to their composite pointer type (Clause [expr]). Comparing pointers is defined as follows: Two pointers compare equal if they are both null, both point to the same function, or both represent the same address ([basic.compound]), otherwise they compare unequal.

If at least one of the operands is a pointer to member, pointer to member conversions ([conv.mem]) and qualification conversions ([conv.qual]) are performed on both operands to bring them to their composite pointer type (Clause [expr]). Comparing pointers to members is defined as follows:

  • If two pointers to members are both the null member pointer value, they compare equal.

  • If only one of two pointers to members is the null member pointer value, they compare unequal.

  • If either is a pointer to a virtual member function, the result is unspecified.

  • If one refers to a member of class C1 and the other refers to a member of a different class C2, where neither is a base class of the other, the result is unspecified. [ Example:

    struct A {};
    struct B : A { int x; };
    struct C : A { int x; };
    
    int A::*bx = (int(A::*))&B::x;
    int A::*cx = (int(A::*))&C::x;
    
    bool b1 = (bx == cx);   // unspecified
    

     — end example ]

  • Otherwise, two pointers to members compare equal if they would refer to the same member of the same most derived object ([intro.object]) or the same subobject if indirection with a hypothetical object of the associated class type were performed, otherwise they compare unequal. [ Example:

    struct B {
      int f();
    };
    struct L : B { };
    struct R : B { };
    struct D : L, R { };
    
    int (B::*pb)() = &B::f;
    int (L::*pl)() = pb;
    int (R::*pr)() = pb;
    int (D::*pdl)() = pl;
    int (D::*pdr)() = pr;
    bool x = (pdl == pdr);          // false
    bool y = (pb == pl);            // true
    

     — end example ]

Two operands of type std::nullptr_t or one operand of type std::nullptr_t and the other a null pointer constant compare equal.

If two operands compare equal, the result is true for the == operator and false for the != operator. If two operands compare unequal, the result is false for the == operator and true for the != operator. Otherwise, the result of each of the operators is unspecified.

If both operands are of arithmetic or enumeration type, the usual arithmetic conversions are performed on both operands; each of the operators shall yield true if the specified relationship is true and false if it is false.