7 Expressions [expr]

7.6 Compound expressions [expr.compound]

7.6.10 Equality operators [expr.eq]

The == (equal to) and the != (not equal to) operators group left-to-right.
The lvalue-to-rvalue ([conv.lval]) and function-to-pointer ([conv.func]) standard conversions are performed on the operands.
If one of the operands is a pointer or a null pointer constant ([conv.ptr]), the array-to-pointer conversion ([conv.array]) is performed on the other operand.
The converted operands shall have scalar type.
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.
Any two pointer values or two pointer-to-member values either compare equal or compare unequal.
[Note 1: 
Repeated comparisons are consistent so long as neither value is an invalid pointer value.
— end note]
If at least one of the converted operands is a pointer, pointer conversions, function pointer conversions, and qualification conversions are performed on both operands to bring them to their composite pointer type.
Comparing pointers is defined as follows:
  • If one pointer represents the address of a complete object, and another pointer represents the address one past the last element of a different complete object,⁶⁰ the result of the comparison is unspecified.
  • Otherwise, if the pointers are both null, both point to the same function, or both represent the same address, they compare equal.
  • Otherwise, the pointers compare unequal.
If at least one of the operands is a pointer to member, pointer-to-member conversions ([conv.mem]), function pointer conversions ([conv.fctptr]), and qualification conversions ([conv.qual]) are performed on both operands to bring them to their composite pointer type ([expr.type]).
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 1: 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]
  • If both refer to (possibly different) members of the same union, they compare equal.
  • Otherwise, two pointers to members compare equal if they would refer to the same member of the same most derived object or the same subobject if indirection with a hypothetical object of the associated class type were performed, otherwise they compare unequal.
    [Example 2: 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 both operands are of type std​::​meta​::​info, they compare equal if both operands and they compare unequal otherwise.
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.
If both operands are of arithmetic or enumeration type, the usual arithmetic conversions ([expr.arith.conv]) are performed on both operands; each of the operators shall yield true if the specified relationship is true and false if it is false.
60)60)
As specified in [basic.compound], an object that is not an array element is considered to belong to a single-element array for this purpose.