8 Expressions [expr]

8.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]), function pointer conversions ([conv.fctptr]), 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:
  • 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,88 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 ([basic.compound]), 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]) 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
    ]
  • If both refer to (possibly different) members of the same union ([class.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 ([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.
An object that is not an array element is considered to belong to a single-element array for this purpose; see [expr.unary.op].