Difference between revisions of "cpp/named req/Container"
m (For const_iterator it's the base type that is const not the iterator itself.) |
(Added N3346 DR.) |
||
(33 intermediate revisions by 8 users not shown) | |||
Line 2: | Line 2: | ||
{{cpp/named req/navbar}} | {{cpp/named req/navbar}} | ||
− | A {{named req|Container}} is an object used to store other objects and taking care of the management of the memory used by the objects it contains. | + | A {{named req/core|Container}} is an object used to store other objects and taking care of the management of the memory used by the objects it contains. |
===Requirements=== | ===Requirements=== | ||
− | + | Given the following types and values: | |
− | + | {{dsc begin}} | |
− | + | {{dsc hitem|Type|Definition}} | |
− | + | {{dsc|{{tt|T}}|an object type}} | |
+ | {{dsc|{{tt|C}}|a container class containing objects of type {{tt|T}}}} | ||
+ | {{dsc hitem|Value|Definition}} | ||
+ | {{dsc|{{c|u}}, {{c|v}}|values of type {{tt|C}} or {{c/core|const C}}}} | ||
+ | {{dsc|{{c|mv}}|a value of type {{tt|C}}}} | ||
+ | {{dsc|{{c|cv}}|a value of type {{c/core|const C}}}} | ||
+ | {{dsc|{{c|lhs}}, {{c|rhs}}|lvalues of type {{tt|C}}}} | ||
+ | {{dsc|{{c|i}}, {{c|j}}|values of type {{tt|C::iterator}} or {{c/core|const C::iterator}}}} | ||
+ | {{dsc end}} | ||
+ | |||
+ | {{tt|C}} satisfies the requirements of {{named req/core|Container}} if the following types, statements, and expressions are well-formed and have the specified semantics: | ||
====Types==== | ====Types==== | ||
− | {|class=wikitable | + | {|class="wikitable" |
− | ! | + | !Type |
+ | !Definition | ||
+ | !Requirements | ||
|- | |- | ||
− | |{{ | + | |{{c/core|typename C::value_type}} |
+ | |{{tt|T}} | ||
+ | |{{tt|T}} is {{rev inl|until=c++11|{{named req|CopyConstructible}}}}{{rev inl|since=c++11|{{named req|Erasable}} from {{tt|C}}}}. | ||
|- | |- | ||
− | |{{ | + | |{{c/core|typename C::reference}} |
+ | |{{tt|T&}} | ||
+ | |rowspan=2 {{n/a|No explicit requirement}} | ||
|- | |- | ||
− | |{{ | + | |{{c/core|typename C::const_reference}} |
+ | |{{c/core|const T&}} | ||
|- | |- | ||
− | |{{ | + | |{{c/core|typename C::iterator}} |
+ | |an iterator type | ||
+ | | | ||
+ | * {{tt|C::iterator}} is a {{named req|ForwardIterator}}, and its [[cpp/iterator#Types and writability|value type]] is {{tt|T}}. | ||
+ | * {{tt|C::iterator}} is convertible to {{tt|C::const_iterator}}. | ||
|- | |- | ||
− | |{{ | + | |{{c/core|typename C::const_iterator}} |
+ | |a constant iterator type | ||
+ | |{{tt|C::const_iterator}} is a {{named req|ForwardIterator}}, and its [[cpp/iterator#Types and writability|value type]] is {{tt|T}}. | ||
|- | |- | ||
− | |{{ | + | |{{c/core|typename C::difference_type}} |
− | | | + | |a signed integer type |
+ | |{{tt|C::difference_type}} is the same as the [[cpp/iterator#Types and writability|difference type]] of {{tt|C::iterator}} and {{tt|C::const_iterator}}. | ||
|- | |- | ||
− | |{{ | + | |{{c/core|typename C::size_type}} |
+ | |an unsigned integer type | ||
+ | |{{tt|C::size_type}} is large enough to represent all non-negative values of {{tt|C::difference_type}}. | ||
|} | |} | ||
− | ==== | + | ====Statements==== |
− | {|class=wikitable | + | {|class="wikitable" |
− | ! | + | !Statement |
+ | !colspan=2|Semantics | ||
+ | !{{nbsp}}Complexity{{nbsp}} | ||
|- | |- | ||
− | |{{c|C | + | |{{c|C c;}} |
+ | |||
+ | {{c|1=C c = C();}} | ||
+ | |Postcondition{{nbsp}} | ||
+ | |{{c|c.empty()}} is {{c|true}}. | ||
+ | |constant | ||
|- | |- | ||
− | |{{c|C( | + | |rowspan=2|{{c|C c(v);}} |
+ | |||
+ | {{c|1=C c = C(v);}} | ||
+ | |Precondition | ||
+ | |{{rrev|since=c++11|If {{c|v}} is not an rvalue of type {{tt|C}}, {{tt|T}} is {{named req|CopyInsertable}} into {{tt|C}}.}} | ||
+ | |rowspan=2|linear<ref>If {{c|v}} is an rvalue of type {{tt|C}}, and {{tt|C}} is not a specialization of {{lc|std::array}} or {{ltt std|cpp/container/inplace_vector}}, the complexity is constant.</ref> | ||
|- | |- | ||
− | |{{c| | + | |Postcondition |
+ | | | ||
+ | * If {{c|v}} is an lvalue, {{c|1=c == v}} is {{c|true}}. | ||
+ | * If {{c|v}} is an rvalue{{rev inl|since=c++11|, and {{c|c}} and {{c|v}} do not refer to the same object}}, {{c|c}} is equal to the value that {{c|v}} had before this construction. | ||
|- | |- | ||
− | + | !colspan=4|Notes | |
|- | |- | ||
− | | | + | |colspan=4|<references/> |
+ | |} | ||
+ | |||
+ | ====Expressions==== | ||
+ | <div style="max-height: 80vh; overflow-y: scroll;"> | ||
+ | {|class="wikitable" | ||
+ | !Expression | ||
+ | !Type | ||
+ | !colspan=2 style="min-width: 480px;"|Semantics | ||
+ | !{{nbsp}}Complexity{{nbsp}} | ||
|- | |- | ||
− | |{{c| | + | |{{c|C()}} |
+ | |{{tt|C}} | ||
+ | |Postcondition{{nbsp}} | ||
+ | |{{c|C().empty()}} is {{c|true}}. | ||
+ | |constant | ||
|- | |- | ||
− | |{{c| | + | |rowspan=2|{{c|C(v)}} |
+ | |rowspan=2|{{tt|C}} | ||
+ | |Precondition | ||
+ | |{{rrev|since=c++11|If {{c|v}} is not an rvalue of type {{tt|C}}, {{tt|T}} is {{named req|CopyInsertable}} into {{tt|C}}.}} | ||
+ | |rowspan=2|constant<ref>If {{c|v}} is an rvalue of type {{tt|C}}, and {{tt|C}} is a specialization of {{lc|std::array}} or {{ltt std|cpp/container/inplace_vector}}, the complexity is linear.</ref> | ||
|- | |- | ||
− | |{{c| | + | |Postcondition |
+ | | | ||
+ | * If {{c|v}} is an lvalue, {{c|1=C(v) == v}} is {{c|true}}. | ||
+ | * If {{c|v}} is an rvalue{{rev inl|since=c++11|, and {{c|C(v)}} and {{c|v}} do not refer to the same object}}, {{c|C(v)}} is equal to the value that {{c|v}} had before this construction. | ||
|- | |- | ||
− | |{{c| | + | |{{c|1=lhs = v}} |
+ | |{{tt|C&}} | ||
+ | |Postcondition | ||
+ | | | ||
+ | * If {{c|v}} is an lvalue, {{c|1=lhs == v}} is {{c|true}}. | ||
+ | * If {{c|v}} is an rvalue{{rev inl|since=c++11|, and {{c|lv}} and {{c|v}} do not refer to the same object}}, {{c|lhs}} is equal to the value that {{c|v}} had before this assignment. | ||
+ | |linear | ||
|- | |- | ||
− | |{{c| | + | |{{c|v.~C()}} |
+ | |{{c/core|void}} | ||
+ | |Effect | ||
+ | |Destroys all elements of {{c|v}} and deallocates all memory obtained. | ||
+ | |linear | ||
|- | |- | ||
− | |{{c| | + | |{{c|mv.begin()}} |
+ | |{{tt|C::iterator}} | ||
+ | |Effect | ||
+ | |Returns an iterator pointing to the first element of {{c|mv}}. | ||
+ | |constant | ||
|- | |- | ||
− | |{{c| | + | |{{c|cv.begin()}} |
+ | |{{tt|C::const_iterator}} | ||
+ | |Effect | ||
+ | |Returns an iterator pointing to the first element of {{c|cv}}. | ||
+ | |constant | ||
|- | |- | ||
− | |{{c| | + | |{{c|mv.end()}} |
− | | | + | |{{tt|C::iterator}} |
+ | |Effect | ||
+ | |Returns the past-the-end iterator of {{c|mv}}. | ||
+ | |constant | ||
|- | |- | ||
− | |{{c| | + | |{{c|cv.end()}} |
+ | |{{tt|C::const_iterator}} | ||
+ | |Effect | ||
+ | |Returns the past-the-end iterator of {{c|cv}}. | ||
+ | |constant | ||
|- | |- | ||
− | |{{c| | + | |{{c|v.cbegin()}}<br>{{mark since c++11}} |
+ | |{{tt|C::const_iterator}} | ||
+ | |Effect | ||
+ | |Returns {{c|const_cast<const C&>(v).begin()}}. | ||
+ | |constant | ||
|- | |- | ||
− | |{{c| | + | |{{c|v.cend()}}<br>{{mark since c++11}} |
+ | |{{tt|C::const_iterator}} | ||
+ | |Effect | ||
+ | |Returns {{c|const_cast<const C&>(v).end()}}. | ||
+ | |constant | ||
|- | |- | ||
− | |{{c| | + | |{{c|1=i <=> j}}<br>{{mark since c++20}} |
+ | |{{ltt std|cpp/utility/compare/strong_ordering}}{{nbsp|4}} | ||
+ | |Constraint | ||
+ | |This expression is only required to be well-formed if {{tt|C::iterator}} satisfies the random access iterator requirements. | ||
+ | |constant | ||
|- | |- | ||
− | ! | + | |{{c|1=u == v}} |
+ | |{{c/core|bool}} | ||
+ | |Effect | ||
+ | |Returns {{rev begin}} | ||
+ | {{rev|until=c++14|{{c multi|u.size() {{==}} v.size() &&| std::equal(u.begin(),| u.end(), v.begin())}}}} | ||
+ | {{rev|since=c++14|{{c multi|std::equal(u.begin(), u.end(),| v.begin(), v.end())}}}} | ||
+ | {{rev end}}. | ||
+ | |linear<ref>If {{c|1=u.size() != v.size()}} is {{c|true}}, the complexity is constant.</ref> | ||
|- | |- | ||
− | |colspan= | + | |{{c|1=u != v}} |
+ | | | ||
+ | |Effect | ||
+ | |Equivalent to {{c|1=!(u == v)}}. | ||
+ | |- | ||
+ | |{{c|lhs.swap(rhs)}} | ||
+ | |||
+ | {{c|swap(lhs, rhs)}} | ||
+ | |{{c/core|void}} | ||
+ | |Effect | ||
+ | |Exchanges the contents of {{c|lhs}} and {{c|rhs}}. | ||
+ | |constant<ref>If {{tt|C}} is a specialization of {{lc|std::array}} or {{ltt std|cpp/container/inplace_vector}}, the complexity is linear.</ref> | ||
+ | |- | ||
+ | |{{c|v.size()}} | ||
+ | |{{tt|C::size_type}} | ||
+ | |Effect | ||
+ | |Returns the number of elements<ref>The number of elements is defined by the rules of constructors, inserts, and erases. It is equal to the value of {{c|std::distance(v.begin(), v.end())}}.</ref> of {{c|v}}. | ||
+ | |constant | ||
+ | |- | ||
+ | |{{c|v.max_size()}} | ||
+ | |{{tt|C::size_type}} | ||
+ | |Effect | ||
+ | |Returns the number of elements of the largest possible container of type {{tt|C}}. | ||
+ | |constant | ||
+ | |- | ||
+ | |{{c|v.empty()}} | ||
+ | |{{c/core|bool}} | ||
+ | |Effect | ||
+ | |Returns {{c|1=v.begin() == v.end()}}. | ||
+ | |constant | ||
+ | |- | ||
+ | !colspan=5|Optional container requirements{{anchor|Optional container requirements}}<br>{{normal|{{small|(only provided for some types of containers)}}}} | ||
+ | |- | ||
+ | |rowspan=2|{{c|1=u <=> v}}<br>{{mark since c++20}} | ||
+ | |rowspan=2|{{lti|cpp/standard library/synth-three-way|synth-three-way-result}}<br>{{nbspt|4}}{{c/core|<C::value_type>}} | ||
+ | |Precondition | ||
+ | |Either {{tt|T}} models {{lconcept|three_way_comparable}}, or {{c/core|operator<}} is a total ordering relationship defined for values of type {{tt|T}} and {{c/core|const T}}. | ||
+ | |rowspan=2|linear | ||
+ | |- | ||
+ | |Effect | ||
+ | |Returns {{box|{{c/core|std::lexicographical_compare_three_way}}<br>{{nbspt|4}}{{c/core|(u.begin(), u.end(),}}<br>{{nbspt|5}}{{c/core|v.begin(), v.end(),}}<br>{{nbspt|5}}{{lti|cpp/standard library/synth-three-way}}{{sep}}{{c/core|)}}}}<ref>If the iterators passed to {{lc|std::lexicographical_compare_three_way}} are {{named req|ConstexprIterator}}s, the operation is implemented by {{c/core|constexpr}} functions.</ref>. | ||
+ | |- | ||
+ | !colspan=5|Notes | ||
+ | |- | ||
+ | |colspan=5|<references/> | ||
|} | |} | ||
+ | </div> | ||
− | + | In the expressions {{c|1=i == j}}, {{c|1=i != j}}, {{c|i < j}}, {{c|1=i <= j}}, {{c|1=i >= j}}, {{c|i > j}} and {{c|i - j}}, if {{c|i}} and/or {{c|j}} are replaced by iterators of type {{tt|C::const_iterator}} pointing to the same element respectively, the semantics remain the same. | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
===Container data races=== | ===Container data races=== | ||
− | + | See [[cpp/container#Thread safety|container thread safety]]. | |
+ | |||
+ | ===Defect reports=== | ||
+ | {{dr list begin}} | ||
+ | {{dr list item|wg=lwg|dr=179|std=C++98|before={{tt|iterator}} and {{tt|const_iterator}} types might be incomparable|after=required to be comparable}} | ||
+ | {{dr list item|wg=lwg|dr=276|std=C++98|before={{tt|T}} was required to be {{named req|CopyAssignable}}|after={{tt|T}} is required to be<br>{{named req|CopyConstructible}}}} | ||
+ | {{dr list item|wg=lwg|dr=322|std=C++98|before=the value types of {{tt|iterator}} and {{tt|const_iterator}} were not specified|after=specified as {{tt|T}}}} | ||
+ | {{dr list item|wg=lwg|dr=774|std=C++98|before=there was no requirement on {{c|swap(a, b)}}|after=added}} | ||
+ | {{dr list item|wg=lwg|dr=883|std=C++98|before={{c|a.swap(b)}} was defined as {{c|swap(a, b)}},<br>resulted in circular definition|after=defined as exchanging<br>the values of {{c|a}} and {{c|b}}}} | ||
+ | {{dr list item|wg=lwg|dr=1319|std=C++98|before={{tt|iterator}} and {{tt|const_iterator}}<br>might not have multipass guarantee|after=they are required to satisfy<br>the requirements of<br>{{named req|ForwardIterator}}}} | ||
+ | {{dr list item|wg=lwg|dr=2114|paper=P2167R3|std=C++98|before=non-{{c/core|bool}} return types of some functions were allowed|after=disallowed}} | ||
+ | {{dr list item|wg=lwg|dr=2182|std=C++98|before=the types deonted by {{tt|reference}} and<br>{{tt|const_reference}} were poorly specified|after=improved wording}} | ||
+ | {{dr list item|wg=lwg|dr=2257|std=C++98|before=two containers required linear time to compare<br>equal even if they have different sizes|after=only requires constant<br>time in this case}} | ||
+ | {{dr list item|wg=lwg|dr=2263|std=C++11|before=the resolution of {{lwg|179}} was accidentally dropped in C++11|after=restored}} | ||
+ | {{dr list item|wg=lwg|dr=2839|std=C++11|before=self move assignment of standard containers was not allowed|after=allowed but the<br>result is unspecified}} | ||
+ | {{dr list item|paper=N3346|std=C++11|before={{tt|C::value_type}} was required to be {{named req|Destructible}}|after=required to be {{named req|Erasable}} from {{tt|C}}}} | ||
+ | {{dr list end}} | ||
− | === | + | ===See also=== |
− | + | {{dsc begin}} | |
− | + | {{dsc see cpp|cpp/container|Containers library|nomono=true}} | |
− | + | {{dsc end}} | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
{{langlinks|de|es|fr|it|ja|pt|ru|zh}} | {{langlinks|de|es|fr|it|ja|pt|ru|zh}} |
Latest revision as of 17:45, 6 November 2024
A Container is an object used to store other objects and taking care of the management of the memory used by the objects it contains.
Contents |
[edit] Requirements
Given the following types and values:
Type | Definition |
T
|
an object type |
C
|
a container class containing objects of type T
|
Value | Definition |
u, v | values of type C or const C
|
mv | a value of type C
|
cv | a value of type const C |
lhs, rhs | lvalues of type C
|
i, j | values of type C::iterator or const C::iterator
|
C
satisfies the requirements of Container if the following types, statements, and expressions are well-formed and have the specified semantics:
[edit] Types
Type | Definition | Requirements |
---|---|---|
typename C::value_type | T
|
T is CopyConstructible(until C++11)Erasable from C (since C++11).
|
typename C::reference | T&
|
No explicit requirement |
typename C::const_reference | const T& | |
typename C::iterator | an iterator type |
|
typename C::const_iterator | a constant iterator type | C::const_iterator is a LegacyForwardIterator, and its value type is T .
|
typename C::difference_type | a signed integer type | C::difference_type is the same as the difference type of C::iterator and C::const_iterator .
|
typename C::size_type | an unsigned integer type | C::size_type is large enough to represent all non-negative values of C::difference_type .
|
[edit] Statements
Statement | Semantics | Complexity | |||
---|---|---|---|---|---|
C c;
C c = C(); |
Postcondition | c.empty() is true. | constant | ||
C c(v);
C c = C(v); |
Precondition |
|
linear[1] | ||
Postcondition |
| ||||
Notes | |||||
|
[edit] Expressions
Expression | Type | Semantics | Complexity | |||||
---|---|---|---|---|---|---|---|---|
C() | C
|
Postcondition | C().empty() is true. | constant | ||||
C(v) | C
|
Precondition |
|
constant[1] | ||||
Postcondition |
| |||||||
lhs = v | C&
|
Postcondition |
|
linear | ||||
v.~C() | void | Effect | Destroys all elements of v and deallocates all memory obtained. | linear | ||||
mv.begin() | C::iterator
|
Effect | Returns an iterator pointing to the first element of mv. | constant | ||||
cv.begin() | C::const_iterator
|
Effect | Returns an iterator pointing to the first element of cv. | constant | ||||
mv.end() | C::iterator
|
Effect | Returns the past-the-end iterator of mv. | constant | ||||
cv.end() | C::const_iterator
|
Effect | Returns the past-the-end iterator of cv. | constant | ||||
v.cbegin() (since C++11) |
C::const_iterator
|
Effect | Returns const_cast<const C&>(v).begin(). | constant | ||||
v.cend() (since C++11) |
C::const_iterator
|
Effect | Returns const_cast<const C&>(v).end(). | constant | ||||
i <=> j (since C++20) |
std::strong_ordering | Constraint | This expression is only required to be well-formed if C::iterator satisfies the random access iterator requirements.
|
constant | ||||
u == v | bool | Effect | Returns
|
linear[2] | ||||
u != v | Effect | Equivalent to !(u == v). | ||||||
lhs.swap(rhs)
swap(lhs, rhs) |
void | Effect | Exchanges the contents of lhs and rhs. | constant[3] | ||||
v.size() | C::size_type
|
Effect | Returns the number of elements[4] of v. | constant | ||||
v.max_size() | C::size_type
|
Effect | Returns the number of elements of the largest possible container of type C .
|
constant | ||||
v.empty() | bool | Effect | Returns v.begin() == v.end(). | constant | ||||
Optional container requirements (only provided for some types of containers) | ||||||||
u <=> v (since C++20) |
synth-three-way-result <C::value_type>
|
Precondition | Either T models three_way_comparable , or operator< is a total ordering relationship defined for values of type T and const T.
|
linear | ||||
Effect | Returns std::lexicographical_compare_three_way (u.begin(), u.end(), v.begin(), v.end(), synth-three-way )[5].
| |||||||
Notes | ||||||||
|
In the expressions i == j, i != j, i < j, i <= j, i >= j, i > j and i - j, if i and/or j are replaced by iterators of type C::const_iterator
pointing to the same element respectively, the semantics remain the same.
[edit] Container data races
[edit] Defect reports
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
LWG 179 | C++98 | iterator and const_iterator types might be incomparable
|
required to be comparable |
LWG 276 | C++98 | T was required to be CopyAssignable
|
T is required to beCopyConstructible |
LWG 322 | C++98 | the value types of iterator and const_iterator were not specified
|
specified as T
|
LWG 774 | C++98 | there was no requirement on swap(a, b) | added |
LWG 883 | C++98 | a.swap(b) was defined as swap(a, b), resulted in circular definition |
defined as exchanging the values of a and b |
LWG 1319 | C++98 | iterator and const_iterator might not have multipass guarantee |
they are required to satisfy the requirements of LegacyForwardIterator |
LWG 2114 (P2167R3) |
C++98 | non-bool return types of some functions were allowed | disallowed |
LWG 2182 | C++98 | the types deonted by reference andconst_reference were poorly specified
|
improved wording |
LWG 2257 | C++98 | two containers required linear time to compare equal even if they have different sizes |
only requires constant time in this case |
LWG 2263 | C++11 | the resolution of LWG issue 179 was accidentally dropped in C++11 | restored |
LWG 2839 | C++11 | self move assignment of standard containers was not allowed | allowed but the result is unspecified |
N3346 | C++11 | C::value_type was required to be Destructible
|
required to be Erasable from C
|
[edit] See also
C++ documentation for Containers library
|