C++ benannte Anforderungen: AssociativeContainer
Ein AssociativeContainer ist ein geordneter Container, der schnelles Nachschlagen von Objekten anhand von Schlüsseln ermöglicht.
Ein assoziativer Container unterstützt eindeutige Schlüssel, wenn er höchstens ein Element für jeden Schlüssel enthalten darf. Andernfalls unterstützt er gleiche Schlüssel.
Inhalt |
[bearbeiten] Anforderungen
Legende | |
X
|
Eine assoziative Containerklasse |
T
|
Der Elementtyp von X |
A
|
Der Allokator-Typ von X: X::allocator_type, falls vorhanden, sonst std::allocator<X::value_type> |
| a | Ein Wert vom Typ X |
| a2 | Ein Wert eines Typs Y, dessen Node-Handles mit X kompatibel sind |
| b | Ein Wert vom Typ X oder const X |
| u | Ein Name einer zu deklarierenden Variablen |
| a_uniq | Ein Wert vom Typ X, wenn X eindeutige Schlüssel unterstützt |
| a_eq | Ein Wert vom Typ X, wenn X gleiche Schlüssel unterstützt |
| a_tran | Ein Wert vom Typ X oder const X, wenn der Typ X::key_compare::is_transparent existiert |
| i, j | Die LegacyInputIteratorn, die auf Elemente verweisen, die implizit in X::value_type konvertierbar sind |
[i, j)
|
Ein gültiger Bereich |
| rg (seit C++23) |
Ein Wert eines Typs R, der container-compatible-range<value_type> modelliert |
| p | Ein gültiger Konstanten-Iterator zu a |
| q | Ein gültiger dereferenzierbarer Konstanten-Iterator zu a |
| r | Ein gültiger dereferenzierbarer Iterator zu a |
| q1, q2 | Ein gültiger Bereich von Konstanten-Iteratoren in a |
| il | Ein Objekt vom Typ std::initializer_list<X::value_type> |
| t | Ein Wert vom Typ X::value_type |
| k | Ein Wert vom Typ X::key_type |
| c | Ein Wert vom Typ X::key_compare oder const X::key_compare |
| kl | Ein Wert, sodass a in Bezug auf c(x, kl) partitioniert ist, wobei x der Schlüsselwert von e ist und e in a liegt |
| ku | Ein Wert, sodass a in Bezug auf !c(ku, x) partitioniert ist, wobei x der Schlüsselwert von e ist und e in a liegt |
| ke | Ein Wert, sodass a in Bezug auf c(x, ke) und !c(ke, x) partitioniert ist, wobei c(x, ke) !c(ke, x) impliziert und wobei x der Schlüsselwert von e ist und e in a liegt |
| kx (seit C++23) |
Ein Wert, sodass
|
| m | Ein Allokator eines Typs, der in A konvertierbar ist |
| nh | Ein nicht-konstantes Rvalue vom Typ X::node_type |
Der Typ X erfüllt AssociativeContainer, wenn
- Der Typ
Xerfüllt Container(bis C++11)AllocatorAwareContainer(seit C++11), - parametrisiert ist mit
Keyund einer OrdnungsrelationCompare, die eine strikt schwache Ordnung auf Elementen vonKeyinduziert, und- Zusätzlich assoziieren std::map und std::multimap einen beliebigen zugeordneten Typ
Tmit demKey. - Das Objekt vom Typ
Comparewird als Vergleichsobjekt eines Containers vom TypXbezeichnet.
- Zusätzlich assoziieren std::map und std::multimap einen beliebigen zugeordneten Typ
- Die folgenden Ausdrücke müssen für alle assoziativen Container gültig sein und ihre angegebenen Effekte haben
[bearbeiten] Typen
| Name | Typ | Anforderungen |
|---|---|---|
key_type
|
Key
|
|
mapped_type
|
T (nur für std::map und std::multimap) |
|
value_type
|
|
Erasable aus X |
key_compare
|
Compare
|
CopyConstructible |
value_compare
|
|
BinaryPredicate |
node_type
|
Eine Spezialisierung der Node-Handle-Klassenschablone, sodass die öffentlichen verschachtelten Typen dieselben Typen wie die entsprechenden Typen in X sind. |
[bearbeiten] Memberfunktionen und Operatoren
| Ausdruck | Ergebnis | Vorbedingungen | Effekte | Gibt zurück | Komplexität |
|---|---|---|---|---|---|
| X(c) | Konstruiert einen leeren Container. Verwendet eine Kopie von c als Vergleichsobjekt | Konstante | |||
| X u = X(); X u; |
key_compare erfüllt die DefaultConstructible-Anforderungen |
Konstruiert einen leeren Container. Verwendet Compare() als Vergleichsobjekt | Konstante | ||
| X(i, j, c) | value_type ist EmplaceConstructible in X aus *i |
Konstruiert einen leeren Container und fügt Elemente aus dem Bereich [i, j) ein; verwendet c als Vergleichsobjekt |
N·log(N) im Allgemeinen, wobei N den Wert std::distance(i, j) hat; linear, wenn [i, j) in Bezug auf value_comp() sortiert ist | ||
| X(i, j) | key_compare erfüllt die DefaultConstructible-Anforderungen. value_type ist EmplaceConstructible in X aus *i |
Konstruiert einen leeren Container und fügt Elemente aus dem Bereich [i, j) ein; verwendet Compare() als Vergleichsobjekt |
|||
| X(from_range, rg, c) (seit C++23) |
value_type ist EmplaceConstructible in X aus *ranges::begin(rg) |
Konstruiert einen leeren Container und fügt jedes Element aus rg ein. Verwendet c als Vergleichsobjekt | N·log(N) im Allgemeinen, wobei N den Wert ranges::distance(rg) hat; linear, wenn rg in Bezug auf value_comp() sortiert ist | ||
| X(from_range, rg) (seit C++23) |
key_compare erfüllt die DefaultConstructible-Anforderungen. value_type ist EmplaceConstructible in X aus *ranges::begin(rg) |
Konstruiert einen leeren Container und fügt jedes Element aus rg ein. Verwendet Compare() als Vergleichsobjekt | |||
| X(il, c) | X(il.begin(), il.end(), c) | ||||
| X(il) | X(il.begin(), il.end()) | ||||
| a = il | X& | value_type ist CopyInsertable in X und CopyAssignable |
Weist den Bereich [il.begin(), il.end()) a zu. Alle vorhandenen Elemente von a werden entweder zugewiesen oder zerstört |
N·log(N) im Allgemeinen, wobei N den Wert il.size() + a.size() hat; linear, wenn [il.begin(), il.end()) in Bezug auf value_comp() sortiert ist | |
| b.key_comp() | X::key_compare
|
Das Vergleichsobjekt, aus dem b konstruiert wurde | Konstante | ||
| b.value_comp() | X::value_compare
|
Ein Objekt von value_compare, das aus dem Vergleichsobjekt konstruiert wurde |
Konstante | ||
| a_uniq.emplace(args) | std::pair< iterator, bool> |
value_type ist EmplaceConstructible in X aus args |
Fügt ein value_type-Objekt t ein, das mit std::forward<Args>(args)... konstruiert wird, genau dann, wenn kein Element im Container mit einem Schlüssel vorhanden ist, der dem Schlüssel von t entspricht |
Die bool-Komponente des zurückgegebenen Paares ist true genau dann, wenn die Einfügung stattfindet, und die Iterator-Komponente des Paares zeigt auf das Element mit einem Schlüssel, der dem Schlüssel von t entspricht | Logarithmisch |
| a_eq.emplace(args) | iterator
|
value_type ist EmplaceConstructible in X aus args |
Fügt ein value_type-Objekt t ein, das mit std::forward<Args>(args)... konstruiert wird. Wenn ein Bereich mit Elementen, die t entsprechen, in a_eq vorhanden ist, wird t am Ende dieses Bereichs eingefügt |
Ein Iterator, der auf das neu eingefügte Element zeigt | Logarithmisch |
| a.emplace_hint(p, args) | iterator
|
Äquivalent zu a.emplace( |
Ein Iterator, der auf das Element mit dem Schlüssel zeigt, der dem neu eingefügten Element entspricht | Logarithmisch im Allgemeinen, aber amortisiert konstant, wenn das Element direkt vor p eingefügt wird | |
| a_uniq.insert(t) | std::pair< iterator, bool> |
Wenn t ein nicht-konstantes Rvalue ist, ist value_type MoveInsertable in X; andernfalls ist value_type CopyInsertable in X |
Fügt t ein, genau dann, wenn kein Element im Container mit einem Schlüssel vorhanden ist, der dem Schlüssel von t entspricht | Die bool-Komponente des zurückgegebenen Paares ist true genau dann, wenn die Einfügung stattfindet, und die iterator-Komponente des Paares zeigt auf das Element mit einem Schlüssel, der dem Schlüssel von t entspricht |
Logarithmisch |
| a_eq.insert(t) | iterator
|
Wenn t ein nicht-konstantes Rvalue ist, ist value_type MoveInsertable in X; andernfalls ist value_type CopyInsertable in X |
Fügt t ein und gibt den Iterator zurück, der auf das neu eingefügte Element zeigt. Wenn ein Bereich mit Elementen, die t entsprechen, in a_eq vorhanden ist, wird t am Ende dieses Bereichs eingefügt | Logarithmisch | |
| a.insert(p, t) | iterator
|
Wenn t ein nicht-konstantes Rvalue ist, ist value_type MoveInsertable in X; andernfalls ist value_type CopyInsertable in X |
Fügt t ein, genau dann, wenn in Containern mit eindeutigen Schlüsseln kein Element mit einem Schlüssel vorhanden ist, der dem Schlüssel von t entspricht; fügt in Containern mit gleichen Schlüsseln immer t ein. t wird so nah wie möglich an die Position unmittelbar vor p eingefügt | Ein Iterator, der auf das Element mit dem Schlüssel zeigt, der dem Schlüssel von t entspricht | Logarithmisch im Allgemeinen, aber amortisiert konstant, wenn t direkt vor p eingefügt wird |
| a.insert(i, j) | void | value_type ist EmplaceConstructible in X aus *i. Weder i noch j sind Iteratoren in a |
Fügt jedes Element aus dem Bereich [i, j) ein, genau dann, wenn in Containern mit eindeutigen Schlüsseln kein Element mit einem Schlüssel vorhanden ist, der dem Schlüssel dieses Elements entspricht; fügt in Containern mit gleichen Schlüsseln immer dieses Element ein |
N·log(a.size() + N), wobei N den Wert std::distance(i, j) hat | |
| a.insert_range(rg) (seit C++23) |
void | value_type ist EmplaceConstructible in X aus *ranges::begin(rg). rg und a überlappen sich nicht |
Fügt jedes Element aus rg ein, genau dann, wenn in Containern mit eindeutigen Schlüsseln kein Element mit einem Schlüssel vorhanden ist, der dem Schlüssel dieses Elements entspricht; fügt in Containern mit gleichen Schlüsseln immer dieses Element ein | N·log(a.size() + N), wobei N den Wert ranges::distance(rg) hat | |
| a.insert(il) | a.insert(il.begin(), il.end()) | ||||
| a_uniq.insert(nh) | insert_return_type
|
nh ist leer oder a_uniq.get_allocator() |
Wenn nh leer ist, hat dies keine Auswirkung. Andernfalls wird das von nh besessene Element eingefügt, genau dann, wenn kein Element im Container mit einem Schlüssel vorhanden ist, der dem Schlüssel von nh.key() entspricht | Wenn nh leer ist, ist inserted false, position ist end() und node ist leer. Andernfalls, wenn die Einfügung stattgefunden hat, ist inserted true, position zeigt auf das eingefügte Element und node ist leer; wenn die Einfügung fehlgeschlagen ist, ist inserted false, node hat den vorherigen Wert von nh und position zeigt auf ein Element mit einem Schlüssel, der dem von nh.key() entspricht |
Logarithmisch |
| a_eq.insert(nh) | iterator
|
nh ist leer oder a_eq.get_allocator() |
Wenn nh leer ist, hat dies keine Auswirkung und gibt a_eq.end() zurück. Andernfalls wird das von nh besessene Element eingefügt und ein Iterator zurückgegeben, der auf das neu eingefügte Element zeigt. Wenn ein Bereich mit Elementen mit Schlüsseln, die nh.key() entsprechen, in a_eq vorhanden ist, wird das Element am Ende dieses Bereichs eingefügt. Stellt sicher: nh ist leer | Logarithmisch | |
| a.insert(p, nh) | iterator
|
nh ist leer oder a.get_allocator() |
Wenn nh leer ist, hat dies keine Auswirkung und gibt a.end() zurück. Andernfalls wird das von nh besessene Element eingefügt, genau dann, wenn in Containern mit eindeutigen Schlüsseln kein Element mit einem Schlüssel vorhanden ist, der dem Schlüssel von nh.key() entspricht; in Containern mit gleichen Schlüsseln wird immer das von nh besessene Element eingefügt. Das Element wird so nah wie möglich an die Position unmittelbar vor p eingefügt. Stellt sicher: nh ist leer, wenn die Einfügung erfolgreich ist, unverändert, wenn die Einfügung fehlschlägt | Ein Iterator, der auf das Element mit dem Schlüssel zeigt, der dem von nh.key() entspricht | Logarithmisch im Allgemeinen, aber amortisiert konstant, wenn das Element direkt vor p eingefügt wird |
| a.extract(k) | node_type
|
Entfernt das erste Element im Container mit einem Schlüssel, der k entspricht | Ein node_type, der das Element besitzt, falls gefunden, andernfalls ein leerer node_type |
log(a.size()) | |
| a_tran.extract(kx) (seit C++23) |
node_type
|
Entfernt das erste Element im Container mit dem Schlüssel r, sodass !c(r, kx) && !c(kx, r) true ist | Ein node_type, der das Element besitzt, falls gefunden, andernfalls ein leerer node_type |
log(a_tran.size()) | |
| a.extract(q) | node_type
|
Entfernt das Element, auf das q zeigt | Ein node_type, der dieses Element besitzt |
Amortisiert konstant | |
| a.merge(a2) | void | a.get_allocator() == a2.get_allocator() |
Versucht, jedes Element in a2 zu extrahieren und es in a mithilfe des Vergleichsobjekts von a einzufügen. In Containern mit eindeutigen Schlüsseln, wenn in a ein Element mit einem Schlüssel vorhanden ist, der dem Schlüssel eines Elements aus a2 entspricht, wird dieses Element nicht aus a2 extrahiert. Stellt sicher: Zeiger und Referenzen auf die übertragenen Elemente von a2 verweisen auf dieselben Elemente, jedoch als Mitglieder von a. Iteratoren, die auf die übertragenen Elemente verweisen, verweisen weiterhin auf ihre Elemente, verhalten sich aber jetzt wie Iteratoren in a, nicht in a2. Wirft: Nichts, es sei denn, das Vergleichsobjekt wirft. | N·log(a.size() + N), wobei N den Wert a2.size() hat | |
| a.erase(k) | size_type
|
Löscht alle Elemente im Container mit einem Schlüssel, der k entspricht | Die Anzahl der gelöschten Elemente | log(a.size()) + a.count(k) | |
| a_tran.erase(kx) (seit C++23) |
size_type
|
Löscht alle Elemente im Container mit dem Schlüssel r, sodass !c(r, kx) && !c(kx, r) true ist | Die Anzahl der gelöschten Elemente | log(a_tran.size()) + a_tran.count(kx) | |
| a.erase(q) | iterator
|
Löscht das Element, auf das von q gezeigt wird | Ein Iterator, der auf das Element unmittelbar nach q vor dem Löschen des Elements zeigt. Wenn kein solches Element vorhanden ist, wird a.end() zurückgegeben | Amortisiert konstant | |
| a.erase(r) | iterator
|
Löscht das Element, auf das von r gezeigt wird | Ein Iterator, der auf das Element unmittelbar nach r vor dem Löschen des Elements zeigt. Wenn kein solches Element vorhanden ist, wird a.end() zurückgegeben | Amortisiert konstant | |
| a.erase(q1, q2) | iterator
|
Löscht alle Elemente im Bereich[q1, q2)
|
Ein Iterator, der auf das Element zeigt, auf das von q2 vor dem Löschen von Elementen gezeigt wurde. Wenn kein solches Element vorhanden ist, wird a.end() zurückgegeben | log(a.size()) + N, wobei N den Wert std::distance(q1, q2) hat | |
| a.clear() | a.erase(a.begin(), a.end()). Stellt sicher: a.empty() ist true | Linear in a.size() | |||
| b.find(k) | iterator; const_iterator für konstantes b |
Ein Iterator, der auf ein Element mit einem Schlüssel zeigt, der k entspricht, oder b.end(), wenn ein solches Element nicht gefunden wird | Logarithmisch | ||
| a_tran.find(ke) | iterator; const_iterator für konstantes a_tran |
Ein Iterator, der auf ein Element mit dem Schlüssel r zeigt, so dass !c(r, ke) && |
Logarithmisch | ||
| b.count(k) | size_type
|
Die Anzahl der Elemente mit einem Schlüssel, der k entspricht | log(b.size()) + b.count(k) | ||
| a_tran.count(ke) | size_type
|
Die Anzahl der Elemente mit dem Schlüssel r, so dass !c(r, ke) && |
log(a_tran.size()) + a_tran.count(ke) | ||
| b.contains(k) | bool | return b.find(k) != b.end(); | |||
| a_tran.contains(ke) | bool |
return |
|||
| b.lower_bound(k) | iterator; const_iterator für konstantes b |
Ein Iterator, der auf das erste Element mit einem Schlüssel zeigt, der nicht kleiner als k ist, oder b.end(), wenn ein solches Element nicht gefunden wird | Logarithmisch | ||
| a_tran.lower_bound(kl) | iterator; const_iterator für konstantes a_tran |
Ein Iterator, der auf das erste Element mit dem Schlüssel r zeigt, so dass !c(r, kl), oder a_tran.end(), wenn ein solches Element nicht gefunden wird | Logarithmisch | ||
| b.upper_bound(k) | iterator; const_iterator für konstantes b |
Ein Iterator, der auf das erste Element mit einem Schlüssel zeigt, der größer als k ist, oder b.end(), wenn ein solches Element nicht gefunden wird | Logarithmisch | ||
| a_tran.upper_bound(ku) | iterator; const_iterator für konstantes a_tran |
Ein Iterator, der auf das erste Element mit dem Schlüssel r zeigt, so dass c(ku, r), oder a_tran.end(), wenn ein solches Element nicht gefunden wird | Logarithmisch | ||
| b.equal_range(k) | std::pair< iterator, iterator>; std::pair< |
Äquivalent zu return |
Logarithmisch | ||
| a_tran.equal_range(ke) | std::pair< iterator, iterator>; std::pair< |
Äquivalent zu return |
Logarithmisch |
[bearbeiten] Iteratoren
Iteratoren assoziativer Container erfüllen die Anforderungen eines LegacyBidirectionalIterator.
Für assoziative Container, bei denen value_type gleich key_type ist, sind sowohl iterator als auch const_iterator konstante Iteratoren. Es ist nicht spezifiziert, ob iterator und const_iterator gleich sind.
Iteratoren assoziativer Container durchlaufen die Container in aufsteigender Reihenfolge der Schlüssel, wobei "aufsteigend" durch den Vergleich definiert ist, der zum Erstellen der Container verwendet wurde. Das heißt, gegeben
- a, ein assoziativer Container
- i und j, dereferenzierbare Iteratoren zu a.
Wenn der Abstand von i zu j positiv ist, dann gilt a.value_comp()(*j, *i) = false. Zusätzlich gilt, wenn a ein assoziativer Container mit eindeutigen Schlüsseln ist, die stärkere Bedingung a.value_comp()(*i, *j) != false.
| Dieser Abschnitt ist unvollständig Grund: Anforderungen fertigstellen. |
[bearbeiten] Standardbibliothek
Die folgenden Standardbibliothekscontainer erfüllen die AssociativeContainer-Anforderungen
| Sammlung eindeutiger Schlüssel, sortiert nach Schlüsseln (Klassenvorlage) | |
| Sammlung von Schlüsseln, sortiert nach Schlüsseln (Klassenvorlage) | |
| Sammlung von Schlüssel-Wert-Paaren, sortiert nach Schlüsseln, Schlüssel sind eindeutig (Klassenvorlage) | |
| Sammlung von Schlüssel-Wert-Paaren, sortiert nach Schlüsseln (Klassenvorlage) |
[bearbeiten] Fehlerberichte
Die folgenden Verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.
| DR | angewendet auf | Verhalten wie veröffentlicht | Korrigiertes Verhalten |
|---|---|---|---|
| LWG 354 | C++98 | lower_bound und upper_bound gabennicht den End-Iterator zurück, wenn kein Element gefunden wurde |
sie geben den End- Iterator in diesem Fall zurück |
| LWG 589 | C++98 | die Elemente, auf die i und j verweisen hatten den Typ X::value_type |
die Elemente sind implizit konvertierbar zu X::value_type |