This commit is contained in:
2025-10-25 03:02:53 +03:00
commit 043225d523
3416 changed files with 681196 additions and 0 deletions

186
cppdraft/expr/eq.md Normal file
View File

@@ -0,0 +1,186 @@
[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)