Files
2025-10-25 03:02:53 +03:00

187 lines
7.7 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[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.10Equality operators[expr.eq]")
[*relational-expression*](expr.rel#nt:relational-expression "7.6.9Relational operators[expr.rel]")
[*equality-expression*](#nt:equality-expression "7.6.10Equality operators[expr.eq]") == [*relational-expression*](expr.rel#nt:relational-expression "7.6.9Relational operators[expr.rel]")
[*equality-expression*](#nt:equality-expression "7.6.10Equality operators[expr.eq]") != [*relational-expression*](expr.rel#nt:relational-expression "7.6.9Relational 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.2Lvalue-to-rvalue conversion"))
and function-to-pointer ([[conv.func]](conv.func "7.3.4Function-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.12Pointer conversions")),
the array-to-pointer conversion ([[conv.array]](conv.array "7.3.3Array-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.12Pointer conversions[conv.ptr]"),[function pointer conversions](conv.fctptr "7.3.14Function pointer conversions[conv.fctptr]"), and[qualification conversions](conv.qual "7.3.6Qualification conversions[conv.qual]") are performed on both operands to bring them to their [composite pointer type](expr.type#def:composite_pointer_type "7.2.2Type[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.4Compound 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.13Pointer-to-member conversions")),
function pointer conversions ([[conv.fctptr]](conv.fctptr "7.3.14Function pointer conversions")), and
qualification conversions ([[conv.qual]](conv.qual "7.3.6Qualification conversions"))
are performed on both operands to bring them to
their composite pointer type ([[expr.type]](expr.type "7.2.2Type"))[.](#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.5Unions[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.2Object 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.6Type 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.12Annotations")),
- [(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.1General")),
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.4Usual 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.4Compound 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)