Init
This commit is contained in:
41
cppdraft/concepts/arithmetic.md
Normal file
41
cppdraft/concepts/arithmetic.md
Normal file
@@ -0,0 +1,41 @@
|
||||
[concepts.arithmetic]
|
||||
|
||||
# 18 Concepts library [[concepts]](./#concepts)
|
||||
|
||||
## 18.4 Language-related concepts [[concepts.lang]](concepts.lang#concepts.arithmetic)
|
||||
|
||||
### 18.4.7 Arithmetic concepts [concepts.arithmetic]
|
||||
|
||||
[ð](#itemdecl:1)
|
||||
|
||||
`template<class T>
|
||||
concept [integral](#concept:integral "18.4.7 Arithmetic concepts [concepts.arithmetic]") = [is_integral_v](meta.type.synop#lib:is_integral_v "21.3.3 Header <type_traits> synopsis [meta.type.synop]")<T>;
|
||||
template<class T>
|
||||
concept [signed_integral](#concept:signed_integral "18.4.7 Arithmetic concepts [concepts.arithmetic]") = [integral](#concept:integral "18.4.7 Arithmetic concepts [concepts.arithmetic]")<T> && [is_signed_v](meta.type.synop#lib:is_signed_v "21.3.3 Header <type_traits> synopsis [meta.type.synop]")<T>;
|
||||
template<class T>
|
||||
concept [unsigned_integral](#concept:unsigned_integral "18.4.7 Arithmetic concepts [concepts.arithmetic]") = [integral](#concept:integral "18.4.7 Arithmetic concepts [concepts.arithmetic]")<T> && <T>;
|
||||
template<class T>
|
||||
concept [floating_point](#concept:floating_point "18.4.7 Arithmetic concepts [concepts.arithmetic]") = is_floating_point_v<T>;
|
||||
`
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L502)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
[signed_integral](#concept:signed_integral "18.4.7 Arithmetic concepts [concepts.arithmetic]") can be modeled even by types that are
|
||||
not signed integer types ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental types")); for example, char[.](#1.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L508)
|
||||
|
||||
[*Note [2](#note-2)*:
|
||||
|
||||
[unsigned_integral](#concept:unsigned_integral "18.4.7 Arithmetic concepts [concepts.arithmetic]") can be modeled even by types that are
|
||||
not unsigned integer types ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental types")); for example, bool[.](#2.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
180
cppdraft/concepts/callable.md
Normal file
180
cppdraft/concepts/callable.md
Normal file
@@ -0,0 +1,180 @@
|
||||
[concepts.callable]
|
||||
|
||||
# 18 Concepts library [[concepts]](./#concepts)
|
||||
|
||||
## 18.7 Callable concepts [concepts.callable]
|
||||
|
||||
### [18.7.1](#general) General [[concepts.callable.general]](concepts.callable.general)
|
||||
|
||||
[1](#general-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L1209)
|
||||
|
||||
The concepts in [concepts.callable] describe the requirements on function
|
||||
objects ([[function.objects]](function.objects "22.10 Function objects")) and their arguments[.](#general-1.sentence-1)
|
||||
|
||||
### [18.7.2](#concept.invocable) Concept invocable [[concept.invocable]](concept.invocable)
|
||||
|
||||
[1](#concept.invocable-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L1215)
|
||||
|
||||
The [invocable](#concept:invocable "18.7.2 Concept invocable [concept.invocable]") concept specifies a relationship between a callable
|
||||
type ([[func.def]](func.def "22.10.3 Definitions")) F and a set of argument types Args... which
|
||||
can be evaluated by the library function invoke ([[func.invoke]](func.invoke "22.10.5 invoke functions"))[.](#concept.invocable-1.sentence-1)
|
||||
|
||||
[ð](#concept:invocable)
|
||||
|
||||
`template<class F, class... Args>
|
||||
concept [invocable](#concept:invocable "18.7.2 Concept invocable [concept.invocable]") = requires(F&& f, Args&&... args) {
|
||||
invoke(std::forward<F>(f), std::forward<Args>(args)...); // not required to be equality-preserving
|
||||
};
|
||||
`
|
||||
|
||||
[2](#concept.invocable-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L1228)
|
||||
|
||||
[*Example [1](#concept.invocable-example-1)*:
|
||||
|
||||
A function that generates random numbers can model [invocable](#concept:invocable "18.7.2 Concept invocable [concept.invocable]"),
|
||||
since the invoke function call expression is not required to be
|
||||
equality-preserving ([[concepts.equality]](concepts.equality "18.2 Equality preservation"))[.](#concept.invocable-2.sentence-1)
|
||||
|
||||
â *end example*]
|
||||
|
||||
### [18.7.3](#concept.regularinvocable) Concept regular_invocable [[concept.regularinvocable]](concept.regularinvocable)
|
||||
|
||||
[ð](#concept:regular_invocable)
|
||||
|
||||
`template<class F, class... Args>
|
||||
concept [regular_invocable](#concept:regular_invocable "18.7.3 Concept regular_invocable [concept.regularinvocable]") = [invocable](#concept:invocable "18.7.2 Concept invocable [concept.invocable]")<F, Args...>;
|
||||
`
|
||||
|
||||
[1](#concept.regularinvocable-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L1244)
|
||||
|
||||
The invoke function call expression shall be
|
||||
equality-preserving ([[concepts.equality]](concepts.equality "18.2 Equality preservation")) and
|
||||
shall not modify the function object or the arguments[.](#concept.regularinvocable-1.sentence-1)
|
||||
|
||||
[*Note [1](#concept.regularinvocable-note-1)*:
|
||||
|
||||
This requirement supersedes the annotation in the definition of[invocable](#concept:invocable "18.7.2 Concept invocable [concept.invocable]")[.](#concept.regularinvocable-1.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[2](#concept.regularinvocable-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L1253)
|
||||
|
||||
[*Example [1](#concept.regularinvocable-example-1)*:
|
||||
|
||||
A random number generator does not model [regular_invocable](#concept:regular_invocable "18.7.3 Concept regular_invocable [concept.regularinvocable]")[.](#concept.regularinvocable-2.sentence-1)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[3](#concept.regularinvocable-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L1258)
|
||||
|
||||
[*Note [2](#concept.regularinvocable-note-2)*:
|
||||
|
||||
The distinction between [invocable](#concept:invocable "18.7.2 Concept invocable [concept.invocable]") and [regular_invocable](#concept:regular_invocable "18.7.3 Concept regular_invocable [concept.regularinvocable]") is purely semantic[.](#concept.regularinvocable-3.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
### [18.7.4](#concept.predicate) Concept predicate [[concept.predicate]](concept.predicate)
|
||||
|
||||
[ð](#concept:predicate)
|
||||
|
||||
`template<class F, class... Args>
|
||||
concept [predicate](#concept:predicate "18.7.4 Concept predicate [concept.predicate]") =
|
||||
[regular_invocable](#concept:regular_invocable "18.7.3 Concept regular_invocable [concept.regularinvocable]")<F, Args...> && [boolean-testable](concept.booleantestable#concept:boolean-testable "18.5.2 Boolean testability [concept.booleantestable]")<invoke_result_t<F, Args...>>;
|
||||
`
|
||||
|
||||
### [18.7.5](#concept.relation) Concept relation [[concept.relation]](concept.relation)
|
||||
|
||||
[ð](#concept:relation)
|
||||
|
||||
`template<class R, class T, class U>
|
||||
concept [relation](#concept:relation "18.7.5 Concept relation [concept.relation]") =
|
||||
[predicate](#concept:predicate "18.7.4 Concept predicate [concept.predicate]")<R, T, T> && [predicate](#concept:predicate "18.7.4 Concept predicate [concept.predicate]")<R, U, U> &&
|
||||
[predicate](#concept:predicate "18.7.4 Concept predicate [concept.predicate]")<R, T, U> && [predicate](#concept:predicate "18.7.4 Concept predicate [concept.predicate]")<R, U, T>;
|
||||
`
|
||||
|
||||
### [18.7.6](#concept.equiv) Concept equivalence_relation [[concept.equiv]](concept.equiv)
|
||||
|
||||
[ð](#concept:equivalence_relation)
|
||||
|
||||
`template<class R, class T, class U>
|
||||
concept [equivalence_relation](#concept:equivalence_relation "18.7.6 Concept equivalence_relation [concept.equiv]") = [relation](#concept:relation "18.7.5 Concept relation [concept.relation]")<R, T, U>;
|
||||
`
|
||||
|
||||
[1](#concept.equiv-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L1290)
|
||||
|
||||
A [relation](#concept:relation "18.7.5 Concept relation [concept.relation]") models [equivalence_relation](#concept:equivalence_relation "18.7.6 Concept equivalence_relation [concept.equiv]") only if
|
||||
it imposes an equivalence relation on its arguments[.](#concept.equiv-1.sentence-1)
|
||||
|
||||
### [18.7.7](#concept.strictweakorder) Concept strict_weak_order [[concept.strictweakorder]](concept.strictweakorder)
|
||||
|
||||
[ð](#concept:strict_weak_order)
|
||||
|
||||
`template<class R, class T, class U>
|
||||
concept [strict_weak_order](#concept:strict_weak_order "18.7.7 Concept strict_weak_order [concept.strictweakorder]") = [relation](#concept:relation "18.7.5 Concept relation [concept.relation]")<R, T, U>;
|
||||
`
|
||||
|
||||
[1](#concept.strictweakorder-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L1303)
|
||||
|
||||
A [relation](#concept:relation "18.7.5 Concept relation [concept.relation]") models [strict_weak_order](#concept:strict_weak_order "18.7.7 Concept strict_weak_order [concept.strictweakorder]") only if
|
||||
it imposes a [*strict weak ordering*](#def:strict_weak_ordering) on its arguments[.](#concept.strictweakorder-1.sentence-1)
|
||||
|
||||
[2](#concept.strictweakorder-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L1307)
|
||||
|
||||
The term[*strict*](#def:strict) refers to the
|
||||
requirement of an irreflexive relation (!comp(x, x) for all x),
|
||||
and the term[*weak*](#def:weak) to requirements that are not as strong as
|
||||
those for a total ordering,
|
||||
but stronger than those for a partial
|
||||
ordering[.](#concept.strictweakorder-2.sentence-1)
|
||||
|
||||
If we defineequiv(a, b) as!comp(a, b) && !comp(b, a),
|
||||
then the requirements are thatcomp andequiv both be transitive relations:
|
||||
|
||||
- [(2.1)](#concept.strictweakorder-2.1)
|
||||
|
||||
comp(a, b) && comp(b, c) impliescomp(a, c)
|
||||
|
||||
- [(2.2)](#concept.strictweakorder-2.2)
|
||||
|
||||
equiv(a, b) && equiv(b, c) impliesequiv(a, c)
|
||||
|
||||
[3](#concept.strictweakorder-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L1338)
|
||||
|
||||
[*Note [1](#concept.strictweakorder-note-1)*:
|
||||
|
||||
Under these conditions, it can be shown that
|
||||
|
||||
- [(3.1)](#concept.strictweakorder-3.1)
|
||||
|
||||
equiv is an equivalence relation,
|
||||
|
||||
- [(3.2)](#concept.strictweakorder-3.2)
|
||||
|
||||
comp induces a well-defined relation on the equivalence
|
||||
classes determined byequiv, and
|
||||
|
||||
- [(3.3)](#concept.strictweakorder-3.3)
|
||||
|
||||
the induced relation is a strict total ordering[.](#concept.strictweakorder-3.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
14
cppdraft/concepts/callable/general.md
Normal file
14
cppdraft/concepts/callable/general.md
Normal file
@@ -0,0 +1,14 @@
|
||||
[concepts.callable.general]
|
||||
|
||||
# 18 Concepts library [[concepts]](./#concepts)
|
||||
|
||||
## 18.7 Callable concepts [[concepts.callable]](concepts.callable#general)
|
||||
|
||||
### 18.7.1 General [concepts.callable.general]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L1209)
|
||||
|
||||
The concepts in [[concepts.callable]](concepts.callable "18.7 Callable concepts") describe the requirements on function
|
||||
objects ([[function.objects]](function.objects "22.10 Function objects")) and their arguments[.](#1.sentence-1)
|
||||
394
cppdraft/concepts/compare.md
Normal file
394
cppdraft/concepts/compare.md
Normal file
@@ -0,0 +1,394 @@
|
||||
[concepts.compare]
|
||||
|
||||
# 18 Concepts library [[concepts]](./#concepts)
|
||||
|
||||
## 18.5 Comparison concepts [concepts.compare]
|
||||
|
||||
### [18.5.1](#general) General [[concepts.compare.general]](concepts.compare.general)
|
||||
|
||||
[1](#general-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L843)
|
||||
|
||||
Subclause [concepts.compare] describes concepts that establish relationships and orderings
|
||||
on values of possibly differing object types[.](#general-1.sentence-1)
|
||||
|
||||
[2](#general-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L847)
|
||||
|
||||
Given an expression E and a type C,
|
||||
let *CONVERT_TO_LVALUE*<C>(E) be:
|
||||
|
||||
- [(2.1)](#general-2.1)
|
||||
|
||||
static_cast<const C&>(as_const(E)) if that is a valid expression, and
|
||||
|
||||
- [(2.2)](#general-2.2)
|
||||
|
||||
static_cast<const C&>(std::move(E)) otherwise[.](#general-2.sentence-1)
|
||||
|
||||
### [18.5.2](#concept.booleantestable) Boolean testability [[concept.booleantestable]](concept.booleantestable)
|
||||
|
||||
[1](#concept.booleantestable-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L859)
|
||||
|
||||
The exposition-only [*boolean-testable*](#concept:boolean-testable "18.5.2 Boolean testability [concept.booleantestable]") concept
|
||||
specifies the requirements on expressions
|
||||
that are convertible to bool and
|
||||
for which the logical operators ([[expr.log.and]](expr.log.and "7.6.14 Logical AND operator"), [[expr.log.or]](expr.log.or "7.6.15 Logical OR operator"), [[expr.unary.op]](expr.unary.op "7.6.2.2 Unary operators"))
|
||||
have the conventional semantics[.](#concept.booleantestable-1.sentence-1)
|
||||
|
||||
[ð](#concept:boolean-testable-impl)
|
||||
|
||||
`template<class T>
|
||||
concept [boolean-testable-impl](#concept:boolean-testable-impl "18.5.2 Boolean testability [concept.booleantestable]") = [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_to [concept.convertible]")<T, bool>; // exposition only
|
||||
`
|
||||
|
||||
[2](#concept.booleantestable-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L871)
|
||||
|
||||
Let e be an expression such thatdecltype((e)) is T[.](#concept.booleantestable-2.sentence-1)
|
||||
|
||||
T models [*boolean-testable-impl*](#concept:boolean-testable-impl "18.5.2 Boolean testability [concept.booleantestable]") only if
|
||||
|
||||
- [(2.1)](#concept.booleantestable-2.1)
|
||||
|
||||
either remove_cvref_t<T> is not a class type, or
|
||||
a search for the names operator&& and operator|| in the scope of remove_cvref_t<T> finds nothing; and
|
||||
|
||||
- [(2.2)](#concept.booleantestable-2.2)
|
||||
|
||||
argument-dependent lookup ([[basic.lookup.argdep]](basic.lookup.argdep "6.5.4 Argument-dependent name lookup"))
|
||||
for the names operator&& and operator|| with T as the only argument type
|
||||
finds no disqualifying declaration (defined below)[.](#concept.booleantestable-2.sentence-2)
|
||||
|
||||
[3](#concept.booleantestable-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L889)
|
||||
|
||||
A [*disqualifying parameter*](#def:parameter,disqualifying "18.5.2 Boolean testability [concept.booleantestable]") is a function parameter whose declared type P
|
||||
|
||||
- [(3.1)](#concept.booleantestable-3.1)
|
||||
|
||||
is not dependent on a template parameter, and
|
||||
there exists an implicit conversion sequence ([[over.best.ics]](over.best.ics "12.2.4.2 Implicit conversion sequences"))
|
||||
from e to P; or
|
||||
|
||||
- [(3.2)](#concept.booleantestable-3.2)
|
||||
|
||||
is dependent on one or more template parameters, and either
|
||||
* [(3.2.1)](#concept.booleantestable-3.2.1)
|
||||
|
||||
P contains no template parameter that
|
||||
participates in template argument deduction ([[temp.deduct.type]](temp.deduct.type "13.10.3.6 Deducing template arguments from a type")), or
|
||||
|
||||
* [(3.2.2)](#concept.booleantestable-3.2.2)
|
||||
|
||||
template argument deduction
|
||||
using the rules for deducing template arguments
|
||||
in a function call ([[temp.deduct.call]](temp.deduct.call "13.10.3.2 Deducing template arguments from a function call")) ande as the argument succeeds[.](#concept.booleantestable-3.sentence-1)
|
||||
|
||||
[4](#concept.booleantestable-4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L912)
|
||||
|
||||
A [*key parameter*](#def:parameter,key "18.5.2 Boolean testability [concept.booleantestable]") of a function template D is a function parameter of type cv X or reference thereto,
|
||||
where X names a specialization of a class template that
|
||||
has the same innermost enclosing non-inline namespace as D, andX contains at least one template parameter that
|
||||
participates in template argument deduction[.](#concept.booleantestable-4.sentence-1)
|
||||
|
||||
[*Example [1](#concept.booleantestable-example-1)*:
|
||||
|
||||
Innamespace Z {template<class> struct C {}; template<class T>void operator&&(C<T> x, T y); template<class T>void operator||(C<type_identity_t<T>> x, T y);} the declaration of Z::operator&& contains one key parameter, C<T> x, and
|
||||
the declaration of Z::operator|| contains no key parameters[.](#concept.booleantestable-4.sentence-2)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[5](#concept.booleantestable-5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L937)
|
||||
|
||||
A [*disqualifying declaration*](#def:declaration,disqualifying "18.5.2 Boolean testability [concept.booleantestable]") is
|
||||
|
||||
- [(5.1)](#concept.booleantestable-5.1)
|
||||
|
||||
a (non-template) function declaration that
|
||||
contains at least one disqualifying parameter; or
|
||||
|
||||
- [(5.2)](#concept.booleantestable-5.2)
|
||||
|
||||
a function template declaration that
|
||||
contains at least one disqualifying parameter, where
|
||||
* [(5.2.1)](#concept.booleantestable-5.2.1)
|
||||
|
||||
at least one disqualifying parameter is a key parameter; or
|
||||
|
||||
* [(5.2.2)](#concept.booleantestable-5.2.2)
|
||||
|
||||
the declaration contains no key parameters; or
|
||||
|
||||
* [(5.2.3)](#concept.booleantestable-5.2.3)
|
||||
|
||||
the declaration declares a function template
|
||||
to which no name is bound ([[dcl.meaning]](dcl.meaning "9.3.4 Meaning of declarators"))[.](#concept.booleantestable-5.sentence-1)
|
||||
|
||||
[6](#concept.booleantestable-6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L955)
|
||||
|
||||
[*Note [1](#concept.booleantestable-note-1)*:
|
||||
|
||||
The intention is to ensure that
|
||||
given two types T1 and T2 that each model [*boolean-testable-impl*](#concept:boolean-testable-impl "18.5.2 Boolean testability [concept.booleantestable]"),
|
||||
the && and || operators within the expressionsdeclval<T1>() && declval<T2>() anddeclval<T1>() || declval<T2>() resolve to the corresponding built-in operators[.](#concept.booleantestable-6.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[ð](#concept:boolean-testable)
|
||||
|
||||
`template<class T>
|
||||
concept [boolean-testable](#concept:boolean-testable "18.5.2 Boolean testability [concept.booleantestable]") = // exposition only
|
||||
[boolean-testable-impl](#concept:boolean-testable-impl "18.5.2 Boolean testability [concept.booleantestable]")<T> && requires(T&& t) {
|
||||
{ !std::forward<T>(t) } -> [boolean-testable-impl](#concept:boolean-testable-impl "18.5.2 Boolean testability [concept.booleantestable]");
|
||||
};
|
||||
`
|
||||
|
||||
[7](#concept.booleantestable-7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L974)
|
||||
|
||||
Let e be an expression such thatdecltype((e)) is T[.](#concept.booleantestable-7.sentence-1)
|
||||
|
||||
T models [*boolean-testable*](#concept:boolean-testable "18.5.2 Boolean testability [concept.booleantestable]") only ifbool(e) == !bool(!e)[.](#concept.booleantestable-7.sentence-2)
|
||||
|
||||
[8](#concept.booleantestable-8)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L980)
|
||||
|
||||
[*Example [2](#concept.booleantestable-example-2)*:
|
||||
|
||||
The typesbool,true_type ([[meta.type.synop]](meta.type.synop "21.3.3 Header <type_traits> synopsis")),int*, andbitset<N>::reference ([[template.bitset]](template.bitset "22.9.2 Class template bitset"))
|
||||
model [*boolean-testable*](#concept:boolean-testable "18.5.2 Boolean testability [concept.booleantestable]")[.](#concept.booleantestable-8.sentence-1)
|
||||
|
||||
â *end example*]
|
||||
|
||||
### [18.5.3](#concept.comparisoncommontype) Comparison common types [[concept.comparisoncommontype]](concept.comparisoncommontype)
|
||||
|
||||
[ð](#concept.comparisoncommontype-itemdecl:1)
|
||||
|
||||
`template<class T, class U, class C = common_reference_t<const T&, const U&>>
|
||||
concept [comparison-common-type-with-impl](#concept:comparison-common-type-with-impl "18.5.3 Comparison common types [concept.comparisoncommontype]") = // exposition only
|
||||
[same_as](concept.same#concept:same_as "18.4.2 Concept same_as [concept.same]")<common_reference_t<const T&, const U&>,
|
||||
common_reference_t<const U&, const T&>> &&
|
||||
requires {
|
||||
requires [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_to [concept.convertible]")<const T&, const C&> || [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_to [concept.convertible]")<T, const C&>;
|
||||
requires [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_to [concept.convertible]")<const U&, const C&> || [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_to [concept.convertible]")<U, const C&>;
|
||||
};
|
||||
|
||||
template<class T, class U>
|
||||
concept [comparison-common-type-with](#concept:comparison-common-type-with "18.5.3 Comparison common types [concept.comparisoncommontype]") = // exposition only
|
||||
[comparison-common-type-with-impl](#concept:comparison-common-type-with-impl "18.5.3 Comparison common types [concept.comparisoncommontype]")<remove_cvref_t<T>, remove_cvref_t<U>>;
|
||||
`
|
||||
|
||||
[1](#concept.comparisoncommontype-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L1007)
|
||||
|
||||
Let C be common_reference_t<const T&, const U&>[.](#concept.comparisoncommontype-1.sentence-1)
|
||||
|
||||
Let t1 and t2 be equality-preserving expressions
|
||||
that are lvalues of type remove_cvref_t<T>, and
|
||||
let u1 and u2 be equality-preserving expressions
|
||||
that are lvalues of type remove_cvref_t<U>[.](#concept.comparisoncommontype-1.sentence-2)
|
||||
|
||||
T and U model[*comparison-common-type-with*](#concept:comparison-common-type-with "18.5.3 Comparison common types [concept.comparisoncommontype]")<T, U> only if
|
||||
|
||||
- [(1.1)](#concept.comparisoncommontype-1.1)
|
||||
|
||||
*CONVERT_TO_LVALUE*<C>(t1) equals*CONVERT_TO_LVALUE*<C>(t2) if and only if t1 equals t2, and
|
||||
|
||||
- [(1.2)](#concept.comparisoncommontype-1.2)
|
||||
|
||||
*CONVERT_TO_LVALUE*<C>(u1) equals*CONVERT_TO_LVALUE*<C>(u2) if and only if u1 equals u2
|
||||
|
||||
### [18.5.4](#concept.equalitycomparable) Concept equality_comparable [[concept.equalitycomparable]](concept.equalitycomparable)
|
||||
|
||||
[ð](#concept:weakly-equality-comparable-with)
|
||||
|
||||
`template<class T, class U>
|
||||
concept [weakly-equality-comparable-with](#concept:weakly-equality-comparable-with "18.5.4 Concept equality_comparable [concept.equalitycomparable]") = // exposition only
|
||||
requires(const remove_reference_t<T>& t,
|
||||
const remove_reference_t<U>& u) {
|
||||
{ t == u } -> [boolean-testable](#concept:boolean-testable "18.5.2 Boolean testability [concept.booleantestable]");
|
||||
{ t != u } -> [boolean-testable](#concept:boolean-testable "18.5.2 Boolean testability [concept.booleantestable]");
|
||||
{ u == t } -> [boolean-testable](#concept:boolean-testable "18.5.2 Boolean testability [concept.booleantestable]");
|
||||
{ u != t } -> [boolean-testable](#concept:boolean-testable "18.5.2 Boolean testability [concept.booleantestable]");
|
||||
};
|
||||
`
|
||||
|
||||
[1](#concept.equalitycomparable-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L1041)
|
||||
|
||||
Given types T and U,
|
||||
let t and u be lvalues of typesconst remove_reference_t<T> andconst remove_reference_t<U> respectively[.](#concept.equalitycomparable-1.sentence-1)
|
||||
|
||||
T and U model[*weakly-equality-comparable-with*](#concept:weakly-equality-comparable-with "18.5.4 Concept equality_comparable [concept.equalitycomparable]")<T, U> only if
|
||||
|
||||
- [(1.1)](#concept.equalitycomparable-1.1)
|
||||
|
||||
t == u, u == t, t != u, and u != t have the same domain[.](#concept.equalitycomparable-1.1.sentence-1)
|
||||
|
||||
- [(1.2)](#concept.equalitycomparable-1.2)
|
||||
|
||||
bool(u == t) == bool(t == u)[.](#concept.equalitycomparable-1.2.sentence-1)
|
||||
|
||||
- [(1.3)](#concept.equalitycomparable-1.3)
|
||||
|
||||
bool(t != u) == !bool(t == u)[.](#concept.equalitycomparable-1.3.sentence-1)
|
||||
|
||||
- [(1.4)](#concept.equalitycomparable-1.4)
|
||||
|
||||
bool(u != t) == bool(t != u)[.](#concept.equalitycomparable-1.4.sentence-1)
|
||||
|
||||
[ð](#concept:equality_comparable)
|
||||
|
||||
`template<class T>
|
||||
concept [equality_comparable](#concept:equality_comparable "18.5.4 Concept equality_comparable [concept.equalitycomparable]") = [weakly-equality-comparable-with](#concept:weakly-equality-comparable-with "18.5.4 Concept equality_comparable [concept.equalitycomparable]")<T, T>;
|
||||
`
|
||||
|
||||
[2](#concept.equalitycomparable-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L1063)
|
||||
|
||||
Let a and b be objects of type T[.](#concept.equalitycomparable-2.sentence-1)
|
||||
|
||||
T models [equality_comparable](#concept:equality_comparable "18.5.4 Concept equality_comparable [concept.equalitycomparable]") only ifbool(a == b) is true when a is equal tob ([[concepts.equality]](concepts.equality "18.2 Equality preservation")), and false otherwise[.](#concept.equalitycomparable-2.sentence-2)
|
||||
|
||||
[3](#concept.equalitycomparable-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L1069)
|
||||
|
||||
[*Note [1](#concept.equalitycomparable-note-1)*:
|
||||
|
||||
The requirement that the expression a == b is equality-preserving
|
||||
implies that == is transitive and symmetric[.](#concept.equalitycomparable-3.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[ð](#concept:equality_comparable_with)
|
||||
|
||||
`template<class T, class U>
|
||||
concept [equality_comparable_with](#concept:equality_comparable_with "18.5.4 Concept equality_comparable [concept.equalitycomparable]") =
|
||||
[equality_comparable](#concept:equality_comparable "18.5.4 Concept equality_comparable [concept.equalitycomparable]")<T> && [equality_comparable](#concept:equality_comparable "18.5.4 Concept equality_comparable [concept.equalitycomparable]")<U> &&
|
||||
[comparison-common-type-with](#concept:comparison-common-type-with "18.5.3 Comparison common types [concept.comparisoncommontype]")<T, U> &&
|
||||
[equality_comparable](#concept:equality_comparable "18.5.4 Concept equality_comparable [concept.equalitycomparable]")<
|
||||
common_reference_t<
|
||||
const remove_reference_t<T>&,
|
||||
const remove_reference_t<U>&>> &&
|
||||
[weakly-equality-comparable-with](#concept:weakly-equality-comparable-with "18.5.4 Concept equality_comparable [concept.equalitycomparable]")<T, U>;
|
||||
`
|
||||
|
||||
[4](#concept.equalitycomparable-4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L1089)
|
||||
|
||||
Given types T and U,
|
||||
let t and t2 be lvalues
|
||||
denoting distinct equal objects of types const remove_reference_t<T> andremove_cvref_t<T>, respectively,
|
||||
let u and u2 be lvalues
|
||||
denoting distinct equal objects of types const remove_reference_t<U> andremove_cvref_t<U>, respectively, and
|
||||
let C be:common_reference_t<const remove_reference_t<T>&, const remove_reference_t<U>&>T and U model[equality_comparable_with](#concept:equality_comparable_with "18.5.4 Concept equality_comparable [concept.equalitycomparable]")<T, U> only ifbool(t == u) == bool(*CONVERT_TO_LVALUE*<C>(t2) == *CONVERT_TO_LVALUE*<C>(u2))
|
||||
|
||||
### [18.5.5](#concept.totallyordered) Concept totally_ordered [[concept.totallyordered]](concept.totallyordered)
|
||||
|
||||
[ð](#concept:totally_ordered)
|
||||
|
||||
`template<class T>
|
||||
concept [totally_ordered](#concept:totally_ordered "18.5.5 Concept totally_ordered [concept.totallyordered]") =
|
||||
[equality_comparable](#concept:equality_comparable "18.5.4 Concept equality_comparable [concept.equalitycomparable]")<T> && [partially-ordered-with](cmp.concept#concept:partially-ordered-with "17.12.4 Concept three_way_comparable [cmp.concept]")<T, T>;
|
||||
`
|
||||
|
||||
[1](#concept.totallyordered-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L1117)
|
||||
|
||||
Given a type T, let a, b, and c be
|
||||
lvalues of type const remove_reference_t<T>[.](#concept.totallyordered-1.sentence-1)
|
||||
|
||||
T models [totally_ordered](#concept:totally_ordered "18.5.5 Concept totally_ordered [concept.totallyordered]") only if
|
||||
|
||||
- [(1.1)](#concept.totallyordered-1.1)
|
||||
|
||||
Exactly one of bool(a < b), bool(a > b), or bool(a == b) is true[.](#concept.totallyordered-1.1.sentence-1)
|
||||
|
||||
- [(1.2)](#concept.totallyordered-1.2)
|
||||
|
||||
If bool(a < b) and bool(b < c), then bool(a < c)[.](#concept.totallyordered-1.2.sentence-1)
|
||||
|
||||
- [(1.3)](#concept.totallyordered-1.3)
|
||||
|
||||
bool(a <= b) == !bool(b < a)[.](#concept.totallyordered-1.3.sentence-1)
|
||||
|
||||
- [(1.4)](#concept.totallyordered-1.4)
|
||||
|
||||
bool(a >= b) == !bool(a < b)[.](#concept.totallyordered-1.4.sentence-1)
|
||||
|
||||
[ð](#concept:totally_ordered_with)
|
||||
|
||||
`template<class T, class U>
|
||||
concept [totally_ordered_with](#concept:totally_ordered_with "18.5.5 Concept totally_ordered [concept.totallyordered]") =
|
||||
[totally_ordered](#concept:totally_ordered "18.5.5 Concept totally_ordered [concept.totallyordered]")<T> && [totally_ordered](#concept:totally_ordered "18.5.5 Concept totally_ordered [concept.totallyordered]")<U> &&
|
||||
[equality_comparable_with](#concept:equality_comparable_with "18.5.4 Concept equality_comparable [concept.equalitycomparable]")<T, U> &&
|
||||
[totally_ordered](#concept:totally_ordered "18.5.5 Concept totally_ordered [concept.totallyordered]")<
|
||||
common_reference_t<
|
||||
const remove_reference_t<T>&,
|
||||
const remove_reference_t<U>&>> &&
|
||||
[partially-ordered-with](cmp.concept#concept:partially-ordered-with "17.12.4 Concept three_way_comparable [cmp.concept]")<T, U>;
|
||||
`
|
||||
|
||||
[2](#concept.totallyordered-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L1144)
|
||||
|
||||
Given types T and U,
|
||||
let t and t2 be lvalues
|
||||
denoting distinct equal objects of types const remove_reference_t<T> andremove_cvref_t<T>, respectively,
|
||||
let u and u2 be lvalues
|
||||
denoting distinct equal objects of types const remove_reference_t<U> andremove_cvref_t<U>, respectively, and
|
||||
let C be:common_reference_t<const remove_reference_t<T>&, const remove_reference_t<U>&>T and U model[totally_ordered_with](#concept:totally_ordered_with "18.5.5 Concept totally_ordered [concept.totallyordered]")<T, U> only if
|
||||
|
||||
- [(2.1)](#concept.totallyordered-2.1)
|
||||
|
||||
bool(t < u) == bool(*CONVERT_TO_LVALUE*<C>(t2) < *CONVERT_TO_LVALUE*<C>(u2))[.](#concept.totallyordered-2.1.sentence-1)
|
||||
|
||||
- [(2.2)](#concept.totallyordered-2.2)
|
||||
|
||||
bool(t > u) == bool(*CONVERT_TO_LVALUE*<C>(t2) > *CONVERT_TO_LVALUE*<C>(u2))[.](#concept.totallyordered-2.2.sentence-1)
|
||||
|
||||
- [(2.3)](#concept.totallyordered-2.3)
|
||||
|
||||
bool(t <= u) == bool(*CONVERT_TO_LVALUE*<C>(t2) <= *CONVERT_TO_LVALUE*<C>(u2))[.](#concept.totallyordered-2.3.sentence-1)
|
||||
|
||||
- [(2.4)](#concept.totallyordered-2.4)
|
||||
|
||||
bool(t >= u) == bool(*CONVERT_TO_LVALUE*<C>(t2) >= *CONVERT_TO_LVALUE*<C>(u2))[.](#concept.totallyordered-2.4.sentence-1)
|
||||
|
||||
- [(2.5)](#concept.totallyordered-2.5)
|
||||
|
||||
bool(u < t) == bool(*CONVERT_TO_LVALUE*<C>(u2) < *CONVERT_TO_LVALUE*<C>(t2))[.](#concept.totallyordered-2.5.sentence-1)
|
||||
|
||||
- [(2.6)](#concept.totallyordered-2.6)
|
||||
|
||||
bool(u > t) == bool(*CONVERT_TO_LVALUE*<C>(u2) > *CONVERT_TO_LVALUE*<C>(t2))[.](#concept.totallyordered-2.6.sentence-1)
|
||||
|
||||
- [(2.7)](#concept.totallyordered-2.7)
|
||||
|
||||
bool(u <= t) == bool(*CONVERT_TO_LVALUE*<C>(u2) <= *CONVERT_TO_LVALUE*<C>(t2))[.](#concept.totallyordered-2.7.sentence-1)
|
||||
|
||||
- [(2.8)](#concept.totallyordered-2.8)
|
||||
|
||||
bool(u >= t) == bool(*CONVERT_TO_LVALUE*<C>(u2) >= *CONVERT_TO_LVALUE*<C>(t2))[.](#concept.totallyordered-2.8.sentence-1)
|
||||
29
cppdraft/concepts/compare/general.md
Normal file
29
cppdraft/concepts/compare/general.md
Normal file
@@ -0,0 +1,29 @@
|
||||
[concepts.compare.general]
|
||||
|
||||
# 18 Concepts library [[concepts]](./#concepts)
|
||||
|
||||
## 18.5 Comparison concepts [[concepts.compare]](concepts.compare#general)
|
||||
|
||||
### 18.5.1 General [concepts.compare.general]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L843)
|
||||
|
||||
Subclause [[concepts.compare]](concepts.compare "18.5 Comparison concepts") describes concepts that establish relationships and orderings
|
||||
on values of possibly differing object types[.](#1.sentence-1)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L847)
|
||||
|
||||
Given an expression E and a type C,
|
||||
let *CONVERT_TO_LVALUE*<C>(E) be:
|
||||
|
||||
- [(2.1)](#2.1)
|
||||
|
||||
static_cast<const C&>(as_const(E)) if that is a valid expression, and
|
||||
|
||||
- [(2.2)](#2.2)
|
||||
|
||||
static_cast<const C&>(std::move(E)) otherwise[.](#2.sentence-1)
|
||||
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*]
|
||||
34
cppdraft/concepts/general.md
Normal file
34
cppdraft/concepts/general.md
Normal file
@@ -0,0 +1,34 @@
|
||||
[concepts.general]
|
||||
|
||||
# 18 Concepts library [[concepts]](./#concepts)
|
||||
|
||||
## 18.1 General [concepts.general]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L6)
|
||||
|
||||
This Clause describes library components that C++ programs may use to perform
|
||||
compile-time validation of template arguments and perform function dispatch
|
||||
based on properties of types[.](#1.sentence-1)
|
||||
|
||||
The purpose of these concepts is to establish
|
||||
a foundation for equational reasoning in programs[.](#1.sentence-2)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L12)
|
||||
|
||||
The following subclauses describe language-related concepts, comparison
|
||||
concepts, object concepts, and callable concepts as summarized in
|
||||
Table [48](#tab:concepts.summary "Table 48: Fundamental concepts library summary")[.](#2.sentence-1)
|
||||
|
||||
Table [48](#tab:concepts.summary) — Fundamental concepts library summary [[tab:concepts.summary]](./tab:concepts.summary)
|
||||
|
||||
| [ð](#tab:concepts.summary-row-1) | **Subclause** | **Header** |
|
||||
| --- | --- | --- |
|
||||
| [ð](#tab:concepts.summary-row-2)<br>[[concepts.equality]](concepts.equality "18.2 Equality preservation") | Equality preservation | |
|
||||
| [ð](#tab:concepts.summary-row-3)<br>[[concepts.lang]](concepts.lang "18.4 Language-related concepts") | Language-related concepts | <concepts> |
|
||||
| [ð](#tab:concepts.summary-row-4)<br>[[concepts.compare]](concepts.compare "18.5 Comparison concepts") | Comparison concepts | |
|
||||
| [ð](#tab:concepts.summary-row-5)<br>[[concepts.object]](concepts.object "18.6 Object concepts") | Object concepts | |
|
||||
| [ð](#tab:concepts.summary-row-6)<br>[[concepts.callable]](concepts.callable "18.7 Callable concepts") | Callable concepts | |
|
||||
608
cppdraft/concepts/lang.md
Normal file
608
cppdraft/concepts/lang.md
Normal file
@@ -0,0 +1,608 @@
|
||||
[concepts.lang]
|
||||
|
||||
# 18 Concepts library [[concepts]](./#concepts)
|
||||
|
||||
## 18.4 Language-related concepts [concepts.lang]
|
||||
|
||||
### [18.4.1](#general) General [[concepts.lang.general]](concepts.lang.general)
|
||||
|
||||
[1](#general-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L293)
|
||||
|
||||
Subclause [concepts.lang] contains the definition of concepts corresponding to language
|
||||
features[.](#general-1.sentence-1)
|
||||
|
||||
These concepts express relationships between types, type
|
||||
classifications, and fundamental type properties[.](#general-1.sentence-2)
|
||||
|
||||
### [18.4.2](#concept.same) Concept same_as [[concept.same]](concept.same)
|
||||
|
||||
[ð](#concept.same-itemdecl:1)
|
||||
|
||||
`template<class T, class U>
|
||||
concept [same-as-impl](#concept:same-as-impl "18.4.2 Concept same_as [concept.same]") = [is_same_v](meta.type.synop#lib:is_same_v "21.3.3 Header <type_traits> synopsis [meta.type.synop]")<T, U>; // exposition only
|
||||
|
||||
template<class T, class U>
|
||||
concept [same_as](#concept:same_as "18.4.2 Concept same_as [concept.same]") = [same-as-impl](#concept:same-as-impl "18.4.2 Concept same_as [concept.same]")<T, U> && [same-as-impl](#concept:same-as-impl "18.4.2 Concept same_as [concept.same]")<U, T>;
|
||||
`
|
||||
|
||||
[1](#concept.same-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L309)
|
||||
|
||||
[*Note [1](#concept.same-note-1)*:
|
||||
|
||||
[same_as](#concept:same_as "18.4.2 Concept same_as [concept.same]")<T, U> subsumes [same_as](#concept:same_as "18.4.2 Concept same_as [concept.same]")<U, T> and
|
||||
vice versa[.](#concept.same-1.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
### [18.4.3](#concept.derived) Concept derived_from [[concept.derived]](concept.derived)
|
||||
|
||||
[ð](#concept:derived_from)
|
||||
|
||||
`template<class Derived, class Base>
|
||||
concept [derived_from](#concept:derived_from "18.4.3 Concept derived_from [concept.derived]") =
|
||||
is_base_of_v<Base, Derived> &&
|
||||
is_convertible_v<const volatile Derived*, const volatile Base*>;
|
||||
`
|
||||
|
||||
[1](#concept.derived-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L326)
|
||||
|
||||
[*Note [1](#concept.derived-note-1)*:
|
||||
|
||||
[derived_from](#concept:derived_from "18.4.3 Concept derived_from [concept.derived]")<Derived, Base> is satisfied if and only ifDerived is publicly and unambiguously derived from Base, orDerived and Base are the same class type ignoring cv-qualifiers[.](#concept.derived-1.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
### [18.4.4](#concept.convertible) Concept convertible_to [[concept.convertible]](concept.convertible)
|
||||
|
||||
[1](#concept.convertible-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L336)
|
||||
|
||||
Given types From and To and
|
||||
an expression E whose type and value category are the same as those of declval<From>(),[convertible_to](#concept:convertible_to "18.4.4 Concept convertible_to [concept.convertible]")<From, To> requires E to be both implicitly and explicitly convertible to type To[.](#concept.convertible-1.sentence-1)
|
||||
|
||||
The implicit and explicit conversions are required to produce equal
|
||||
results[.](#concept.convertible-1.sentence-2)
|
||||
|
||||
[ð](#concept:convertible_to)
|
||||
|
||||
`template<class From, class To>
|
||||
concept [convertible_to](#concept:convertible_to "18.4.4 Concept convertible_to [concept.convertible]") =
|
||||
is_convertible_v<From, To> &&
|
||||
requires {
|
||||
static_cast<To>(declval<From>());
|
||||
};
|
||||
`
|
||||
|
||||
[2](#concept.convertible-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L355)
|
||||
|
||||
Let FromR be add_rvalue_reference_t<From> andtest be the invented function:To test(FromR (&f)()) {return f();} and let f be a function with no arguments and return type FromR such that f() is equality-preserving[.](#concept.convertible-2.sentence-1)
|
||||
|
||||
Types From and To model [convertible_to](#concept:convertible_to "18.4.4 Concept convertible_to [concept.convertible]")<From, To> only if:
|
||||
|
||||
- [(2.1)](#concept.convertible-2.1)
|
||||
|
||||
To is not an object or reference-to-object type, orstatic_cast<To>(f()) is equal to test(f)[.](#concept.convertible-2.1.sentence-1)
|
||||
|
||||
- [(2.2)](#concept.convertible-2.2)
|
||||
|
||||
FromR is not a reference-to-object type, or
|
||||
* [(2.2.1)](#concept.convertible-2.2.1)
|
||||
|
||||
If FromR is an rvalue reference to a non const-qualified type, the
|
||||
resulting state of the object referenced by f() after either above
|
||||
expression is valid but unspecified ([[lib.types.movedfrom]](lib.types.movedfrom "16.4.6.17 Moved-from state of library types"))[.](#concept.convertible-2.2.1.sentence-1)
|
||||
|
||||
* [(2.2.2)](#concept.convertible-2.2.2)
|
||||
|
||||
Otherwise, the object referred to by f() is not modified by either above
|
||||
expression[.](#concept.convertible-2.2.2.sentence-1)
|
||||
|
||||
### [18.4.5](#concept.commonref) Concept common_reference_with [[concept.commonref]](concept.commonref)
|
||||
|
||||
[1](#concept.commonref-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L390)
|
||||
|
||||
For two types T and U, if common_reference_t<T, U> is well-formed and denotes a type C such that both[convertible_to](#concept:convertible_to "18.4.4 Concept convertible_to [concept.convertible]")<T, C> and[convertible_to](#concept:convertible_to "18.4.4 Concept convertible_to [concept.convertible]")<U, C> are modeled, then T and U share a[*common reference type*](#def:common_reference_type), C[.](#concept.commonref-1.sentence-1)
|
||||
|
||||
[*Note [1](#concept.commonref-note-1)*:
|
||||
|
||||
C can be the same as T or U, or can be a
|
||||
different type[.](#concept.commonref-1.sentence-2)
|
||||
|
||||
C can be a reference type[.](#concept.commonref-1.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[ð](#concept:common_reference_with)
|
||||
|
||||
`template<class T, class U>
|
||||
concept [common_reference_with](#concept:common_reference_with "18.4.5 Concept common_reference_with [concept.commonref]") =
|
||||
[same_as](#concept:same_as "18.4.2 Concept same_as [concept.same]")<common_reference_t<T, U>, common_reference_t<U, T>> &&
|
||||
[convertible_to](#concept:convertible_to "18.4.4 Concept convertible_to [concept.convertible]")<T, common_reference_t<T, U>> &&
|
||||
[convertible_to](#concept:convertible_to "18.4.4 Concept convertible_to [concept.convertible]")<U, common_reference_t<T, U>>;
|
||||
`
|
||||
|
||||
[2](#concept.commonref-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L412)
|
||||
|
||||
Let C be common_reference_t<T, U>[.](#concept.commonref-2.sentence-1)
|
||||
|
||||
Let t1 and t2 be equality-preserving
|
||||
expressions ([[concepts.equality]](concepts.equality "18.2 Equality preservation")) such thatdecltype((t1)) and decltype((t2)) are each T, and
|
||||
let u1 and u2 be equality-preserving expressions such thatdecltype((u1)) and decltype((u2)) are each U[.](#concept.commonref-2.sentence-2)
|
||||
|
||||
T and U model [common_reference_with](#concept:common_reference_with "18.4.5 Concept common_reference_with [concept.commonref]")<T, U> only if
|
||||
|
||||
- [(2.1)](#concept.commonref-2.1)
|
||||
|
||||
C(t1) equals C(t2) if and only if t1 equals t2, and
|
||||
|
||||
- [(2.2)](#concept.commonref-2.2)
|
||||
|
||||
C(u1) equals C(u2) if and only if u1 equals u2[.](#concept.commonref-2.sentence-3)
|
||||
|
||||
[3](#concept.commonref-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L428)
|
||||
|
||||
[*Note [2](#concept.commonref-note-2)*:
|
||||
|
||||
Users can customize the behavior of [common_reference_with](#concept:common_reference_with "18.4.5 Concept common_reference_with [concept.commonref]") by specializing
|
||||
the basic_common_reference class template ([[meta.trans.other]](meta.trans.other "21.3.9.7 Other transformations"))[.](#concept.commonref-3.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
### [18.4.6](#concept.common) Concept common_with [[concept.common]](concept.common)
|
||||
|
||||
[1](#concept.common-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L437)
|
||||
|
||||
If T and U can both be explicitly converted to some third type,C, then T and U share a [*common type*](#def:common_type),C[.](#concept.common-1.sentence-1)
|
||||
|
||||
[*Note [1](#concept.common-note-1)*:
|
||||
|
||||
C can be the same as T or U, or can be a
|
||||
different type[.](#concept.common-1.sentence-2)
|
||||
|
||||
C is not necessarily unique[.](#concept.common-1.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[ð](#concept:common_with)
|
||||
|
||||
`template<class T, class U>
|
||||
concept [common_with](#concept:common_with "18.4.6 Concept common_with [concept.common]") =
|
||||
[same_as](#concept:same_as "18.4.2 Concept same_as [concept.same]")<common_type_t<T, U>, common_type_t<U, T>> &&
|
||||
requires {
|
||||
static_cast<common_type_t<T, U>>(declval<T>());
|
||||
static_cast<common_type_t<T, U>>(declval<U>());
|
||||
} &&
|
||||
[common_reference_with](#concept:common_reference_with "18.4.5 Concept common_reference_with [concept.commonref]")<
|
||||
add_lvalue_reference_t<const T>,
|
||||
add_lvalue_reference_t<const U>> &&
|
||||
[common_reference_with](#concept:common_reference_with "18.4.5 Concept common_reference_with [concept.commonref]")<
|
||||
add_lvalue_reference_t<common_type_t<T, U>>,
|
||||
common_reference_t<
|
||||
add_lvalue_reference_t<const T>,
|
||||
add_lvalue_reference_t<const U>>>;
|
||||
`
|
||||
|
||||
[2](#concept.common-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L465)
|
||||
|
||||
Let C be common_type_t<T, U>[.](#concept.common-2.sentence-1)
|
||||
|
||||
Let t1 and t2 be
|
||||
equality-preserving expressions ([[concepts.equality]](concepts.equality "18.2 Equality preservation")) such thatdecltype((t1)) and decltype((t2)) are each T, and
|
||||
let u1 and u2 be equality-preserving expressions such thatdecltype((u1)) and decltype((u2)) are each U[.](#concept.common-2.sentence-2)
|
||||
|
||||
T and U model [common_with](#concept:common_with "18.4.6 Concept common_with [concept.common]")<T, U> only if
|
||||
|
||||
- [(2.1)](#concept.common-2.1)
|
||||
|
||||
C(t1) equals C(t2) if and only if t1 equals t2, and
|
||||
|
||||
- [(2.2)](#concept.common-2.2)
|
||||
|
||||
C(u1) equals C(u2) if and only if u1 equals u2[.](#concept.common-2.sentence-3)
|
||||
|
||||
[3](#concept.common-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L481)
|
||||
|
||||
[*Note [2](#concept.common-note-2)*:
|
||||
|
||||
Users can customize the behavior of [common_with](#concept:common_with "18.4.6 Concept common_with [concept.common]") by specializing thecommon_type class template ([[meta.trans.other]](meta.trans.other "21.3.9.7 Other transformations"))[.](#concept.common-3.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
### [18.4.7](#concepts.arithmetic) Arithmetic concepts [[concepts.arithmetic]](concepts.arithmetic)
|
||||
|
||||
[ð](#concepts.arithmetic-itemdecl:1)
|
||||
|
||||
`template<class T>
|
||||
concept [integral](#concept:integral "18.4.7 Arithmetic concepts [concepts.arithmetic]") = [is_integral_v](meta.type.synop#lib:is_integral_v "21.3.3 Header <type_traits> synopsis [meta.type.synop]")<T>;
|
||||
template<class T>
|
||||
concept [signed_integral](#concept:signed_integral "18.4.7 Arithmetic concepts [concepts.arithmetic]") = [integral](#concept:integral "18.4.7 Arithmetic concepts [concepts.arithmetic]")<T> && [is_signed_v](meta.type.synop#lib:is_signed_v "21.3.3 Header <type_traits> synopsis [meta.type.synop]")<T>;
|
||||
template<class T>
|
||||
concept [unsigned_integral](#concept:unsigned_integral "18.4.7 Arithmetic concepts [concepts.arithmetic]") = [integral](#concept:integral "18.4.7 Arithmetic concepts [concepts.arithmetic]")<T> && <T>;
|
||||
template<class T>
|
||||
concept [floating_point](#concept:floating_point "18.4.7 Arithmetic concepts [concepts.arithmetic]") = is_floating_point_v<T>;
|
||||
`
|
||||
|
||||
[1](#concepts.arithmetic-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L502)
|
||||
|
||||
[*Note [1](#concepts.arithmetic-note-1)*:
|
||||
|
||||
[signed_integral](#concept:signed_integral "18.4.7 Arithmetic concepts [concepts.arithmetic]") can be modeled even by types that are
|
||||
not signed integer types ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental types")); for example, char[.](#concepts.arithmetic-1.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[2](#concepts.arithmetic-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L508)
|
||||
|
||||
[*Note [2](#concepts.arithmetic-note-2)*:
|
||||
|
||||
[unsigned_integral](#concept:unsigned_integral "18.4.7 Arithmetic concepts [concepts.arithmetic]") can be modeled even by types that are
|
||||
not unsigned integer types ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental types")); for example, bool[.](#concepts.arithmetic-2.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
### [18.4.8](#concept.assignable) Concept assignable_from [[concept.assignable]](concept.assignable)
|
||||
|
||||
[ð](#concept:assignable_from)
|
||||
|
||||
`template<class LHS, class RHS>
|
||||
concept [assignable_from](#concept:assignable_from "18.4.8 Concept assignable_from [concept.assignable]") =
|
||||
is_lvalue_reference_v<LHS> &&
|
||||
[common_reference_with](#concept:common_reference_with "18.4.5 Concept common_reference_with [concept.commonref]")<const remove_reference_t<LHS>&, const remove_reference_t<RHS>&> &&
|
||||
requires(LHS lhs, RHS&& rhs) {
|
||||
{ lhs = std::forward<RHS>(rhs) } -> [same_as](#concept:same_as "18.4.2 Concept same_as [concept.same]")<LHS>;
|
||||
};
|
||||
`
|
||||
|
||||
[1](#concept.assignable-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L528)
|
||||
|
||||
Let:
|
||||
|
||||
- [(1.1)](#concept.assignable-1.1)
|
||||
|
||||
lhs be an lvalue that refers to an object lcopy such that decltype((lhs)) is LHS,
|
||||
|
||||
- [(1.2)](#concept.assignable-1.2)
|
||||
|
||||
rhs be an expression such that decltype((rhs)) is RHS, and
|
||||
|
||||
- [(1.3)](#concept.assignable-1.3)
|
||||
|
||||
rcopy be a distinct object that is equal to rhs[.](#concept.assignable-1.sentence-1)
|
||||
|
||||
LHS and RHS model[assignable_from](#concept:assignable_from "18.4.8 Concept assignable_from [concept.assignable]")<LHS, RHS> only if
|
||||
|
||||
- [(1.4)](#concept.assignable-1.4)
|
||||
|
||||
addressof(lhs = rhs) == addressof(lcopy)[.](#concept.assignable-1.4.sentence-1)
|
||||
|
||||
- [(1.5)](#concept.assignable-1.5)
|
||||
|
||||
After evaluating lhs = rhs:
|
||||
* [(1.5.1)](#concept.assignable-1.5.1)
|
||||
|
||||
lhs is equal to rcopy, unless rhs is a non-const
|
||||
xvalue that refers to lcopy[.](#concept.assignable-1.5.1.sentence-1)
|
||||
|
||||
* [(1.5.2)](#concept.assignable-1.5.2)
|
||||
|
||||
If rhs is a non-const xvalue, the resulting state of the
|
||||
object to which it refers is valid but unspecified ([[lib.types.movedfrom]](lib.types.movedfrom "16.4.6.17 Moved-from state of library types"))[.](#concept.assignable-1.5.2.sentence-1)
|
||||
|
||||
* [(1.5.3)](#concept.assignable-1.5.3)
|
||||
|
||||
Otherwise, if rhs is a glvalue, the object to which it refers is
|
||||
not modified[.](#concept.assignable-1.5.3.sentence-1)
|
||||
|
||||
[2](#concept.assignable-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L555)
|
||||
|
||||
[*Note [1](#concept.assignable-note-1)*:
|
||||
|
||||
Assignment need not be a total function ([[structure.requirements]](structure.requirements "16.3.2.3 Requirements"));
|
||||
in particular, if assignment to an object x can result in a modification
|
||||
of some other object y, then x = y is likely not in the domain
|
||||
of =[.](#concept.assignable-2.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
### [18.4.9](#concept.swappable) Concept swappable [[concept.swappable]](concept.swappable)
|
||||
|
||||
[1](#concept.swappable-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L566)
|
||||
|
||||
Let t1 and t2 be equality-preserving expressions that denote
|
||||
distinct equal objects of type T, and let u1 and u2 similarly denote distinct equal objects of type U[.](#concept.swappable-1.sentence-1)
|
||||
|
||||
[*Note [1](#concept.swappable-note-1)*:
|
||||
|
||||
t1 and u1 can denote distinct objects, or the same object[.](#concept.swappable-1.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
An operation[*exchanges the values*](#def:exchanges_the_values) denoted by t1 and u1 if and only
|
||||
if the operation modifies neither t2 nor u2 and:
|
||||
|
||||
- [(1.1)](#concept.swappable-1.1)
|
||||
|
||||
If T and U are the same type, the result of the operation
|
||||
is that t1 equals u2 and u1 equals t2[.](#concept.swappable-1.1.sentence-1)
|
||||
|
||||
- [(1.2)](#concept.swappable-1.2)
|
||||
|
||||
If T and U are different types and [common_reference_with](#concept:common_reference_with "18.4.5 Concept common_reference_with [concept.commonref]")<decltype((t1)), decltype((u1))> is modeled,
|
||||
the result of the operation is that C(t1) equals C(u2) and C(u1) equals C(t2) where C is common_reference_t<decltype((t1)), decltype((u1))>[.](#concept.swappable-1.2.sentence-1)
|
||||
|
||||
[2](#concept.swappable-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L590)
|
||||
|
||||
The name ranges::swap denotes a customization point
|
||||
object ([[customization.point.object]](customization.point.object "16.3.3.3.5 Customization Point Object types"))[.](#concept.swappable-2.sentence-1)
|
||||
|
||||
The expressionranges::swap(E1, E2) for subexpressions E1 and E2 is expression-equivalent to an expressionS determined as follows:
|
||||
|
||||
- [(2.1)](#concept.swappable-2.1)
|
||||
|
||||
S is (void)swap(E1, E2)[192](#footnote-192 "The name swap is used here unqualified.") if E1 or E2 has class or enumeration type ([[basic.compound]](basic.compound "6.9.4 Compound types")) and that expression is valid, with
|
||||
overload resolution performed in a context that includes the declarationtemplate<class T>void swap(T&, T&) = delete; and does not include a declaration of ranges::swap[.](#concept.swappable-2.1.sentence-1)
|
||||
If the function selected by overload resolution does not
|
||||
exchange the values denoted by E1 and E2,
|
||||
the program is ill-formed, no diagnostic required[.](#concept.swappable-2.1.sentence-2)
|
||||
[*Note [2](#concept.swappable-note-2)*:
|
||||
This precludes calling unconstrained program-defined overloads of swap[.](#concept.swappable-2.1.sentence-3)
|
||||
When the deleted overload is viable, program-defined overloads
|
||||
need to be more specialized ([[temp.func.order]](temp.func.order "13.7.7.3 Partial ordering of function templates")) to be selected[.](#concept.swappable-2.1.sentence-4)
|
||||
â *end note*]
|
||||
|
||||
- [(2.2)](#concept.swappable-2.2)
|
||||
|
||||
Otherwise, if E1 and E2 are lvalues of array types ([[basic.compound]](basic.compound "6.9.4 Compound types"))
|
||||
with equal extent and ranges::swap(*E1, *E2) is a valid expression, S is (void)ranges::swap_ranges(E1, E2),
|
||||
except that noexcept(S) is equal to noexcept(ranges::swap(*E1, *E2))[.](#concept.swappable-2.2.sentence-1)
|
||||
|
||||
- [(2.3)](#concept.swappable-2.3)
|
||||
|
||||
Otherwise, if E1 and E2 are lvalues of the
|
||||
same type T that models [move_constructible](#concept:move_constructible "18.4.13 Concept move_constructible [concept.moveconstructible]")<T> and [assignable_from](#concept:assignable_from "18.4.8 Concept assignable_from [concept.assignable]")<T&, T>, S is an expression that exchanges the denoted values[.](#concept.swappable-2.3.sentence-1)
|
||||
S is a constant expression if
|
||||
* [(2.3.1)](#concept.swappable-2.3.1)
|
||||
|
||||
T is a literal type ([[basic.types.general]](basic.types.general#term.literal.type "6.9.1 General")),
|
||||
|
||||
* [(2.3.2)](#concept.swappable-2.3.2)
|
||||
|
||||
both E1 = std::move(E2) and E2 = std::move(E1) are
|
||||
constant subexpressions ([[defns.const.subexpr]](defns.const.subexpr "3.15 constant subexpression")), and
|
||||
|
||||
* [(2.3.3)](#concept.swappable-2.3.3)
|
||||
|
||||
the full-expressions of the initializers in the declarationsT t1(std::move(E1));
|
||||
T t2(std::move(E2)); are constant subexpressions.
|
||||
|
||||
noexcept(S) is equal to is_nothrow_move_constructible_v<T> && is_nothrow_move_assignable_v<T>[.](#concept.swappable-2.3.sentence-2)
|
||||
|
||||
- [(2.4)](#concept.swappable-2.4)
|
||||
|
||||
Otherwise, ranges::swap(E1, E2) is ill-formed[.](#concept.swappable-2.4.sentence-1)
|
||||
[*Note [3](#concept.swappable-note-3)*:
|
||||
This case can result in substitution failure when ranges::swap(E1, E2) appears in the immediate context of a template instantiation[.](#concept.swappable-2.4.sentence-2)
|
||||
â *end note*]
|
||||
|
||||
[3](#concept.swappable-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L660)
|
||||
|
||||
[*Note [4](#concept.swappable-note-4)*:
|
||||
|
||||
Whenever ranges::swap(E1, E2) is a valid expression, it
|
||||
exchanges the values denoted byE1 and E2 and has type void[.](#concept.swappable-3.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[ð](#concept:swappable)
|
||||
|
||||
`template<class T>
|
||||
concept [swappable](#concept:swappable "18.4.9 Concept swappable [concept.swappable]") = requires(T& a, T& b) { ranges::swap(a, b); };
|
||||
`
|
||||
|
||||
[ð](#concept:swappable_with)
|
||||
|
||||
`template<class T, class U>
|
||||
concept [swappable_with](#concept:swappable_with "18.4.9 Concept swappable [concept.swappable]") =
|
||||
[common_reference_with](#concept:common_reference_with "18.4.5 Concept common_reference_with [concept.commonref]")<T, U> &&
|
||||
requires(T&& t, U&& u) {
|
||||
ranges::swap(std::forward<T>(t), std::forward<T>(t));
|
||||
ranges::swap(std::forward<U>(u), std::forward<U>(u));
|
||||
ranges::swap(std::forward<T>(t), std::forward<U>(u));
|
||||
ranges::swap(std::forward<U>(u), std::forward<T>(t));
|
||||
};
|
||||
`
|
||||
|
||||
[4](#concept.swappable-4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L684)
|
||||
|
||||
[*Note [5](#concept.swappable-note-5)*:
|
||||
|
||||
The semantics of the [swappable](#concept:swappable "18.4.9 Concept swappable [concept.swappable]") and [swappable_with](#concept:swappable_with "18.4.9 Concept swappable [concept.swappable]") concepts are fully defined by the ranges::swap customization point object[.](#concept.swappable-4.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[5](#concept.swappable-5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L690)
|
||||
|
||||
[*Example [1](#concept.swappable-example-1)*:
|
||||
|
||||
User code can ensure that the evaluation of swap calls
|
||||
is performed in an appropriate context under the various conditions as follows:#include <cassert>#include <concepts>#include <utility>namespace ranges = std::ranges;
|
||||
|
||||
template<class T, std::[swappable_with](#concept:swappable_with "18.4.9 Concept swappable [concept.swappable]")<T> U>void value_swap(T&& t, U&& u) { ranges::swap(std::forward<T>(t), std::forward<U>(u));}template<std::[swappable](#concept:swappable "18.4.9 Concept swappable [concept.swappable]") T>void lv_swap(T& t1, T& t2) { ranges::swap(t1, t2);}namespace N {struct A { int m; }; struct Proxy { A* a;
|
||||
Proxy(A& a) : a{&a} {}friend void swap(Proxy x, Proxy y) { ranges::swap(*x.a, *y.a); }};
|
||||
Proxy proxy(A& a) { return Proxy{ a }; }}int main() {int i = 1, j = 2;
|
||||
lv_swap(i, j);
|
||||
assert(i == 2 && j == 1);
|
||||
|
||||
N::A a1 = { 5 }, a2 = { -5 };
|
||||
value_swap(a1, proxy(a2));
|
||||
assert(a1.m == -5 && a2.m == 5);}
|
||||
|
||||
â *end example*]
|
||||
|
||||
[192)](#footnote-192)[192)](#footnoteref-192)
|
||||
|
||||
The name swap is used
|
||||
here unqualified[.](#footnote-192.sentence-1)
|
||||
|
||||
### [18.4.10](#concept.destructible) Concept destructible [[concept.destructible]](concept.destructible)
|
||||
|
||||
[1](#concept.destructible-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L737)
|
||||
|
||||
The [destructible](#concept:destructible "18.4.10 Concept destructible [concept.destructible]") concept specifies properties of all types,
|
||||
instances of which can be destroyed at the end of their lifetime, or reference
|
||||
types[.](#concept.destructible-1.sentence-1)
|
||||
|
||||
[ð](#concept:destructible)
|
||||
|
||||
`template<class T>
|
||||
concept [destructible](#concept:destructible "18.4.10 Concept destructible [concept.destructible]") = [is_nothrow_destructible_v](meta.type.synop#lib:is_nothrow_destructible_v "21.3.3 Header <type_traits> synopsis [meta.type.synop]")<T>;
|
||||
`
|
||||
|
||||
[2](#concept.destructible-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L748)
|
||||
|
||||
[*Note [1](#concept.destructible-note-1)*:
|
||||
|
||||
Unlike the [*Cpp17Destructible*](utility.arg.requirements#:Cpp17Destructible "16.4.4.2 Template argument requirements [utility.arg.requirements]") requirements (Table [35](utility.arg.requirements#tab:cpp17.destructible "Table 35: Cpp17Destructible requirements")), this
|
||||
concept forbids destructors that are potentially throwing, even if a particular
|
||||
invocation of the destructor does not actually throw[.](#concept.destructible-2.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
### [18.4.11](#concept.constructible) Concept constructible_from [[concept.constructible]](concept.constructible)
|
||||
|
||||
[1](#concept.constructible-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L758)
|
||||
|
||||
The [constructible_from](#concept:constructible_from "18.4.11 Concept constructible_from [concept.constructible]") concept constrains the initialization of a
|
||||
variable of a given type with a particular set of argument types[.](#concept.constructible-1.sentence-1)
|
||||
|
||||
[ð](#concept:constructible_from)
|
||||
|
||||
`template<class T, class... Args>
|
||||
concept [constructible_from](#concept:constructible_from "18.4.11 Concept constructible_from [concept.constructible]") = [destructible](#concept:destructible "18.4.10 Concept destructible [concept.destructible]")<T> && [is_constructible_v](meta.type.synop#lib:is_constructible_v "21.3.3 Header <type_traits> synopsis [meta.type.synop]")<T, Args...>;
|
||||
`
|
||||
|
||||
### [18.4.12](#concept.default.init) Concept default_initializable [[concept.default.init]](concept.default.init)
|
||||
|
||||
[ð](#concept:default_initializable)
|
||||
|
||||
`template<class T>
|
||||
constexpr bool is-default-initializable = see below; // exposition only
|
||||
|
||||
template<class T>
|
||||
concept [default_initializable](#concept:default_initializable "18.4.12 Concept default_initializable [concept.default.init]") = [constructible_from](#concept:constructible_from "18.4.11 Concept constructible_from [concept.constructible]")<T> &&
|
||||
requires { T{}; } &&
|
||||
is-default-initializable<T>;
|
||||
`
|
||||
|
||||
[1](#concept.default.init-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L780)
|
||||
|
||||
For a type T, *is-default-initializable*<T> is true if and only if the variable definitionT t; is well-formed for some invented variable t;
|
||||
otherwise it is false[.](#concept.default.init-1.sentence-1)
|
||||
|
||||
Access checking is performed as if in a context unrelated to T[.](#concept.default.init-1.sentence-2)
|
||||
|
||||
Only the validity of the immediate context of the variable initialization is considered[.](#concept.default.init-1.sentence-3)
|
||||
|
||||
### [18.4.13](#concept.moveconstructible) Concept move_constructible [[concept.moveconstructible]](concept.moveconstructible)
|
||||
|
||||
[ð](#concept:move_constructible)
|
||||
|
||||
`template<class T>
|
||||
concept [move_constructible](#concept:move_constructible "18.4.13 Concept move_constructible [concept.moveconstructible]") = [constructible_from](#concept:constructible_from "18.4.11 Concept constructible_from [concept.constructible]")<T, T> && [convertible_to](#concept:convertible_to "18.4.4 Concept convertible_to [concept.convertible]")<T, T>;
|
||||
`
|
||||
|
||||
[1](#concept.moveconstructible-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L800)
|
||||
|
||||
If T is an object type, then let rv be an rvalue of typeT and u2 a distinct object of type T equal torv[.](#concept.moveconstructible-1.sentence-1)
|
||||
|
||||
T models [move_constructible](#concept:move_constructible "18.4.13 Concept move_constructible [concept.moveconstructible]") only if
|
||||
|
||||
- [(1.1)](#concept.moveconstructible-1.1)
|
||||
|
||||
After the definition T u = rv;, u is equal to u2[.](#concept.moveconstructible-1.1.sentence-1)
|
||||
|
||||
- [(1.2)](#concept.moveconstructible-1.2)
|
||||
|
||||
T(rv) is equal to u2[.](#concept.moveconstructible-1.2.sentence-1)
|
||||
|
||||
- [(1.3)](#concept.moveconstructible-1.3)
|
||||
|
||||
If T is not const, rv's resulting state is valid
|
||||
but unspecified ([[lib.types.movedfrom]](lib.types.movedfrom "16.4.6.17 Moved-from state of library types")); otherwise, it is unchanged[.](#concept.moveconstructible-1.3.sentence-1)
|
||||
|
||||
### [18.4.14](#concept.copyconstructible) Concept copy_constructible [[concept.copyconstructible]](concept.copyconstructible)
|
||||
|
||||
[ð](#concept:copy_constructible)
|
||||
|
||||
`template<class T>
|
||||
concept [copy_constructible](#concept:copy_constructible "18.4.14 Concept copy_constructible [concept.copyconstructible]") =
|
||||
[move_constructible](#concept:move_constructible "18.4.13 Concept move_constructible [concept.moveconstructible]")<T> &&
|
||||
[constructible_from](#concept:constructible_from "18.4.11 Concept constructible_from [concept.constructible]")<T, T&> && [convertible_to](#concept:convertible_to "18.4.4 Concept convertible_to [concept.convertible]")<T&, T> &&
|
||||
[constructible_from](#concept:constructible_from "18.4.11 Concept constructible_from [concept.constructible]")<T, const T&> && [convertible_to](#concept:convertible_to "18.4.4 Concept convertible_to [concept.convertible]")<const T&, T> &&
|
||||
[constructible_from](#concept:constructible_from "18.4.11 Concept constructible_from [concept.constructible]")<T, const T> && [convertible_to](#concept:convertible_to "18.4.4 Concept convertible_to [concept.convertible]")<const T, T>;
|
||||
`
|
||||
|
||||
[1](#concept.copyconstructible-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L826)
|
||||
|
||||
If T is an object type, then let v be an lvalue of typeT or const T or an rvalue of type const T[.](#concept.copyconstructible-1.sentence-1)
|
||||
|
||||
T models [copy_constructible](#concept:copy_constructible "18.4.14 Concept copy_constructible [concept.copyconstructible]") only if
|
||||
|
||||
- [(1.1)](#concept.copyconstructible-1.1)
|
||||
|
||||
After the definition T u = v;,u is equal to v ([[concepts.equality]](concepts.equality "18.2 Equality preservation")) andv is not modified[.](#concept.copyconstructible-1.1.sentence-1)
|
||||
|
||||
- [(1.2)](#concept.copyconstructible-1.2)
|
||||
|
||||
T(v) is equal to v and does not modify v[.](#concept.copyconstructible-1.2.sentence-1)
|
||||
17
cppdraft/concepts/lang/general.md
Normal file
17
cppdraft/concepts/lang/general.md
Normal file
@@ -0,0 +1,17 @@
|
||||
[concepts.lang.general]
|
||||
|
||||
# 18 Concepts library [[concepts]](./#concepts)
|
||||
|
||||
## 18.4 Language-related concepts [[concepts.lang]](concepts.lang#general)
|
||||
|
||||
### 18.4.1 General [concepts.lang.general]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L293)
|
||||
|
||||
Subclause [[concepts.lang]](concepts.lang "18.4 Language-related concepts") contains the definition of concepts corresponding to language
|
||||
features[.](#1.sentence-1)
|
||||
|
||||
These concepts express relationships between types, type
|
||||
classifications, and fundamental type properties[.](#1.sentence-2)
|
||||
49
cppdraft/concepts/object.md
Normal file
49
cppdraft/concepts/object.md
Normal file
@@ -0,0 +1,49 @@
|
||||
[concepts.object]
|
||||
|
||||
# 18 Concepts library [[concepts]](./#concepts)
|
||||
|
||||
## 18.6 Object concepts [concepts.object]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L1172)
|
||||
|
||||
This subclause describes concepts that specify the basis of the
|
||||
value-oriented programming style on which the library is based[.](#1.sentence-1)
|
||||
|
||||
[ð](#itemdecl:1)
|
||||
|
||||
`template<class T>
|
||||
concept [movable](#concept:movable "18.6 Object concepts [concepts.object]") = is_object_v<T> && [move_constructible](concept.moveconstructible#concept:move_constructible "18.4.13 Concept move_constructible [concept.moveconstructible]")<T> &&
|
||||
[assignable_from](concept.assignable#concept:assignable_from "18.4.8 Concept assignable_from [concept.assignable]")<T&, T> && [swappable](concept.swappable#concept:swappable "18.4.9 Concept swappable [concept.swappable]")<T>;
|
||||
template<class T>
|
||||
concept [copyable](#concept:copyable "18.6 Object concepts [concepts.object]") = [copy_constructible](concept.copyconstructible#concept:copy_constructible "18.4.14 Concept copy_constructible [concept.copyconstructible]")<T> && [movable](#concept:movable "18.6 Object concepts [concepts.object]")<T> && [assignable_from](concept.assignable#concept:assignable_from "18.4.8 Concept assignable_from [concept.assignable]")<T&, T&> &&
|
||||
[assignable_from](concept.assignable#concept:assignable_from "18.4.8 Concept assignable_from [concept.assignable]")<T&, const T&> && [assignable_from](concept.assignable#concept:assignable_from "18.4.8 Concept assignable_from [concept.assignable]")<T&, const T>;
|
||||
template<class T>
|
||||
concept [semiregular](#concept:semiregular "18.6 Object concepts [concepts.object]") = [copyable](#concept:copyable "18.6 Object concepts [concepts.object]")<T> && [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_initializable [concept.default.init]")<T>;
|
||||
template<class T>
|
||||
concept [regular](#concept:regular "18.6 Object concepts [concepts.object]") = [semiregular](#concept:semiregular "18.6 Object concepts [concepts.object]")<T> && [equality_comparable](concept.equalitycomparable#concept:equality_comparable "18.5.4 Concept equality_comparable [concept.equalitycomparable]")<T>;
|
||||
`
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L1190)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
The [semiregular](#concept:semiregular "18.6 Object concepts [concepts.object]") concept is modeled by types that behave similarly
|
||||
to fundamental types like int, except that they need not
|
||||
be comparable with ==[.](#2.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/concepts.tex#L1197)
|
||||
|
||||
[*Note [2](#note-2)*:
|
||||
|
||||
The [regular](#concept:regular "18.6 Object concepts [concepts.object]") concept is modeled by types that behave similarly to
|
||||
fundamental types like int and that are comparable with==[.](#3.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
9
cppdraft/concepts/syn.md
Normal file
9
cppdraft/concepts/syn.md
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user