Init
This commit is contained in:
184
cppdraft/concepts/equality.md
Normal file
184
cppdraft/concepts/equality.md
Normal 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.2 Equality 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.1 General [expr.prim.id.general]") ([[expr.prim.id]](expr.prim.id "7.5.5 Names")), and
|
||||
|
||||
- [(1.2)](#1.2)
|
||||
|
||||
invocations of the library function templatesstd::move,std::forward, andstd::declval ([[forward]](forward "22.2.4 Forward/move helpers"), [[declval]](declval "22.2.6 Function 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.2 Equality 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.1 General [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.1 General [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.1 General [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*]
|
||||
Reference in New Issue
Block a user