[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)