[expr.eq]

# 7 Expressions [[expr]](./#expr)

## 7.6 Compound expressions [[expr.compound]](expr.compound#expr.eq)

### 7.6.10 Equality operators [expr.eq]

[equality-expression:](#nt:equality-expression "7.6.10 Equality operators [expr.eq]")  
[*relational-expression*](expr.rel#nt:relational-expression "7.6.9 Relational operators [expr.rel]")  
[*equality-expression*](#nt:equality-expression "7.6.10 Equality operators [expr.eq]") == [*relational-expression*](expr.rel#nt:relational-expression "7.6.9 Relational operators [expr.rel]")  
[*equality-expression*](#nt:equality-expression "7.6.10 Equality operators [expr.eq]") != [*relational-expression*](expr.rel#nt:relational-expression "7.6.9 Relational operators [expr.rel]")

[1](#1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7512)

The == (equal to) and the != (not equal to) operators
group left-to-right[.](#1.sentence-1)

The
lvalue-to-rvalue ([[conv.lval]](conv.lval "7.3.2 Lvalue-to-rvalue conversion"))
and function-to-pointer ([[conv.func]](conv.func "7.3.4 Function-to-pointer conversion"))
standard conversions are performed on the operands[.](#1.sentence-2)

If one of the operands is a pointer or a null pointer constant ([[conv.ptr]](conv.ptr "7.3.12 Pointer conversions")),
the array-to-pointer conversion ([[conv.array]](conv.array "7.3.3 Array-to-pointer conversion")) is performed
on the other operand[.](#1.sentence-3)

[2](#2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7523)

The converted operands shall have scalar type[.](#2.sentence-1)

The operators== and != both yield true or false, i.e., a
result of type bool[.](#2.sentence-2)

In each case below, the operands shall have the
same type after the specified conversions have been applied[.](#2.sentence-3)

[3](#3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7529)

If at least one of the converted operands is a pointer,[pointer conversions](conv.ptr "7.3.12 Pointer conversions [conv.ptr]"),[function pointer conversions](conv.fctptr "7.3.14 Function pointer conversions [conv.fctptr]"), and[qualification conversions](conv.qual "7.3.6 Qualification conversions [conv.qual]") are performed on both operands to bring them to their [composite pointer type](expr.type#def:composite_pointer_type "7.2.2 Type [expr.type]")[.](#3.sentence-1)

Comparing pointers is defined as follows:

- [(3.1)](#3.1)

  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,[66](#footnote-66 "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.") the result of the comparison is unspecified[.](#3.1.sentence-1)

- [(3.2)](#3.2)

  Otherwise, if the pointers are both null, both point to the samefunction, or both[represent the same address](basic.compound#def:represents_the_address "6.9.4 Compound types [basic.compound]"),
they compare equal[.](#3.2.sentence-1)

- [(3.3)](#3.3)

  Otherwise, the pointers compare unequal[.](#3.3.sentence-1)

[4](#4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7559)

If at least one of the operands is a pointer to member,
pointer-to-member conversions ([[conv.mem]](conv.mem "7.3.13 Pointer-to-member conversions")),
function pointer conversions ([[conv.fctptr]](conv.fctptr "7.3.14 Function pointer conversions")), and
qualification conversions ([[conv.qual]](conv.qual "7.3.6 Qualification conversions"))
are performed on both operands to bring them to
their composite pointer type ([[expr.type]](expr.type "7.2.2 Type"))[.](#4.sentence-1)

Comparing pointers to members is defined as follows:

- [(4.1)](#4.1)

  If two pointers to members are both the null member pointer value, they compare
equal[.](#4.1.sentence-1)

- [(4.2)](#4.2)

  If only one of two pointers to members is the null member pointer value, they
compare unequal[.](#4.2.sentence-1)

- [(4.3)](#4.3)

  If either is a pointer to a virtual member function, the result is unspecified[.](#4.3.sentence-1)

- [(4.4)](#4.4)

  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[.](#4.4.sentence-1)
  [*Example [1](#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*]

- [(4.5)](#4.5)

  If both refer to (possibly different) members of the same [union](class.union "11.5 Unions [class.union]"),
they compare equal[.](#4.5.sentence-1)

- [(4.6)](#4.6)

  Otherwise, two pointers to members compare equal if they would refer to the same member of
the same [most derived object](intro.object#def:most_derived_object "6.8.2 Object model [intro.object]") or the same subobject if
indirection with a hypothetical object of the associated
class type were performed, otherwise they compare unequal[.](#4.6.sentence-1)
  [*Example [2](#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); // falsebool y = (pb == pl); // true â *end example*]

[5](#5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7625)

Two operands of type std​::​nullptr_t or one operand of typestd​::​nullptr_t and the other a null pointer constant compare equal[.](#5.sentence-1)

[6](#6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7629)

If both operands are of type std​::​meta​::​info,
they compare equal if both operands

- [(6.1)](#6.1)

are null reflection values,

- [(6.2)](#6.2)

represent values that are template-argument-equivalent ([[temp.type]](temp.type "13.6 Type equivalence")),

- [(6.3)](#6.3)

represent the same object,

- [(6.4)](#6.4)

represent the same entity,

- [(6.5)](#6.5)

represent the same annotation ([[dcl.attr.annotation]](dcl.attr.annotation "9.13.12 Annotations")),

- [(6.6)](#6.6)

represent the same direct base class relationship, or

- [(6.7)](#6.7)

represent equal data member descriptions ([[class.mem.general]](class.mem.general "11.4.1 General")),

and they compare unequal otherwise[.](#6.sentence-1)

[7](#7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7643)

If two operands compare equal, the result is true for
the == operator and false for the != operator[.](#7.sentence-1)

If two operands
compare unequal, the result is false for the == operator andtrue for the != operator[.](#7.sentence-2)

Otherwise, the result of each of the
operators is unspecified[.](#7.sentence-3)

[8](#8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7650)

If both operands are of arithmetic or enumeration type, the usual arithmetic
conversions ([[expr.arith.conv]](expr.arith.conv "7.4 Usual arithmetic conversions")) are performed on both operands; each of the operators shall yieldtrue if the specified relationship is true and false if it is
false[.](#8.sentence-1)

[66)](#footnote-66)[66)](#footnoteref-66)

As specified in [[basic.compound]](basic.compound "6.9.4 Compound types"),
an object that is not an array element is
considered to belong to a single-element array for this purpose[.](#footnote-66.sentence-1)
