[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*]
