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

View File

@@ -0,0 +1,184 @@
[concepts.equality]
# 18 Concepts library [[concepts]](./#concepts)
## 18.2 Equality preservation [concepts.equality]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L27)
An expression is [*equality-preserving*](#def:expression,equality-preserving "18.2Equality preservation[concepts.equality]") if,
given equal inputs, the expression results in equal outputs[.](#1.sentence-1)
The inputs to an
expression are the set of the expression's operands[.](#1.sentence-2)
The output of an expression
is the expression's result and all operands modified by the expression[.](#1.sentence-3)
For the purposes of this subclause,
the operands of an expression are the largest subexpressions that include only:
- [(1.1)](#1.1)
an [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") ([[expr.prim.id]](expr.prim.id "7.5.5Names")), and
- [(1.2)](#1.2)
invocations of the library function templatesstd::move,std::forward, andstd::declval ([[forward]](forward "22.2.4Forward/move helpers"), [[declval]](declval "22.2.6Function template declval"))[.](#1.sentence-4)
[*Example [1](#example-1)*:
The operands of the expression a = std::move(b) area and std::move(b)[.](#1.sentence-5)
— *end example*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L48)
Not all input values need be valid for a given expression[.](#2.sentence-1)
[*Example [2](#example-2)*:
For integers a and b,
the expression a / b is not well-defined
when b is 0[.](#2.sentence-2)
This does not preclude the expression a / b being equality-preserving[.](#2.sentence-3)
— *end example*]
The [*domain*](#def:expression,domain "18.2Equality preservation[concepts.equality]") of an expression is the set of
input values for which the expression is required to be well-defined[.](#2.sentence-4)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L59)
Expressions required to be equality-preserving are further
required to be stable: two evaluations of such an expression with the same input
objects are required to have equal outputs absent any explicit intervening
modification of those input objects[.](#3.sentence-1)
[*Note [1](#note-1)*:
This requirement allows generic code to reason about the current values of
objects based on knowledge of the prior values as observed via
equality-preserving expressions[.](#3.sentence-2)
It effectively forbids spontaneous changes to
an object, changes to an object from another thread of execution, changes to an
object as side effects of non-modifying expressions, and changes to an object as
side effects of modifying a distinct object if those changes could be observable
to a library function via an equality-preserving expression that is required to
be valid for that object[.](#3.sentence-3)
— *end note*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L75)
Expressions declared in a [*requires-expression*](expr.prim.req.general#nt:requires-expression "7.5.8.1General[expr.prim.req.general]") in the library clauses are
required to be equality-preserving, except for those annotated with the comment
“not required to be equality-preserving[.](#4.sentence-1)”
An expression so annotated
may be equality-preserving, but is not required to be so[.](#4.sentence-2)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L81)
An expression that may alter the value of one or more of its inputs in a manner
observable to equality-preserving expressions is said to modify those inputs[.](#5.sentence-1)
The library clauses use a notational convention to specify which expressions declared
in a [*requires-expression*](expr.prim.req.general#nt:requires-expression "7.5.8.1General[expr.prim.req.general]") modify which inputs: except where
otherwise specified, an expression operand that is a non-constant lvalue or
rvalue may be modified[.](#5.sentence-2)
Operands that are constant lvalues or rvalues are
required to not be modified[.](#5.sentence-3)
For the purposes of this subclause,
the cv-qualification and value category of each operand
are determined by assuming
that each template type parameter
denotes a cv-unqualified complete non-array object type[.](#5.sentence-4)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L95)
Where a [*requires-expression*](expr.prim.req.general#nt:requires-expression "7.5.8.1General[expr.prim.req.general]") declares an expression that is
non-modifying for some constant lvalue operand, additional variations of that
expression that accept a non-constant lvalue or (possibly constant) rvalue for
the given operand are also required except where such an expression variation is
explicitly required with differing semantics[.](#6.sentence-1)
These[*implicit expression variations*](#def:implicit_expression_variations) are required to meet the semantic
requirements of the declared expression[.](#6.sentence-2)
The extent to which an implementation
validates the syntax of the variations is unspecified[.](#6.sentence-3)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L105)
[*Example [3](#example-3)*: template<class T> concept C = requires(T a, T b, const T c, const T d) { c == d; // #1 a = std::move(b); // #2 a = c; // #3};
For the above example:
- [(7.1)](#7.1)
Expression #1 does not modify either of its operands, #2 modifies both of its
operands, and #3 modifies only its first operand a[.](#7.1.sentence-1)
- [(7.2)](#7.2)
Expression #1 implicitly requires additional expression variations that meet
the requirements for c == d (including non-modification), as if the
expressions c == b;
c == std::move(d); c == std::move(b);
std::move(c) == d; std::move(c) == b;
std::move(c) == std::move(d); std::move(c) == std::move(b);
a== d; a == b;
a == std::move(d); a == std::move(b);
std::move(a) == d; std::move(a) == b;
std::move(a) == std::move(d); std::move(a) == std::move(b); had been declared as well[.](#7.2.sentence-1)
- [(7.3)](#7.3)
Expression #3 implicitly requires additional expression variations that meet
the requirements for a = c (including non-modification of the second
operand), as if the expressions a = b and a = std::move(c) had
been declared[.](#7.3.sentence-1)
Expression #3 does not implicitly require an expression
variation with a non-constant rvalue second operand, since expression #2
already specifies exactly such an expression explicitly[.](#7.3.sentence-2)
— *end example*]
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L148)
[*Example [4](#example-4)*:
The following type T meets the explicitly stated syntactic requirements
of concept C above but does not meet the additional implicit
requirements:struct T {bool operator==(const T&) const { return true; }bool operator==(T&) = delete;};
T fails to meet the implicit requirements of C,
so T satisfies but does not model C[.](#8.sentence-2)
Since implementations are not required to validate the syntax
of implicit requirements, it is unspecified whether an implementation diagnoses
as ill-formed a program that requires C<T>[.](#8.sentence-3)
— *end example*]