C++-Iterator-Unterstützung für Delphi-Aufzählungstypen und -Container
Nach oben zu Sprachunterstützung für die RAD Studio-Bibliotheken (C++)
Auf dieser Seite wird die aktuelle C++-Iterator-Unterstützung für Delphi-Aufzählungstypen und -Container beschrieben. Die folgende Tabelle enthält eine Übersicht über die unterstützten Typen und Container:
Inhaltsverzeichnis
Richtlinien
Die meisten Iteratoren werden vom System definiert und werden als Templates vom Compiler durch ADL und SFINAE ausgewählt. Das bedeutet, dass sie mit den meisten Typen funktionieren, aber bei ungewöhnlichen Interfaces oder ungewöhnlichem Verhalten in Ihren eigenen Typen könnte das Schreiben eines Iterators erforderlich sein. TDictionary unterstützt, obwohl es ein Aufzählungstyp ist, keinen wahlfreien Zugriff an einem Index und kann deshalb random_access_iterator nicht verwenden. Für TDictionary ist ein eigener Iterator definiert. Die folgenden Richtlinien dienen als Faustregel dafür, welche Iteratoren für einen Typ verwendet werden können.
- Wenn der Typ nur eine
GetEnumerator()
-Methode hat, können Sie das bereichsbasierte for und eine begrenzte Anzahl von schreibgeschützten STL-Algorithmen verwenden. - Wenn der Typ einen Indizierungsoperator (
operator[]
) hat, können Sie das bereichsbasierte for und alle schreibgeschützten STL-Algorithmen verwenden.
- Hinweis: TDictionary ist indizierbar, aber lässt keinen wahlfreien Zugriff zu. Es ist ein TEnumerable.
- Wenn der Typ eine Art von
System::DynamicArray<T>
ist, können Sie das bereichsbasierte for und alle STL-Algorithmen verwenden. Beachten Sie, dass viele Delphi-RTL-Type "Aliase" fürSystem::DynamicArray<T>
, wieArrayofstring
,TIntegerDynArray
,TStringDynArray
und viele andere, sind.
DynamicArray<T>::iterator
DynamicArray<T>::iterator
ist definiert als ein interner Typ von DynamicArray<T>
; daher implementiert er begin()
und end()
als Member-Funktionen. Die restlichen unterstützten Iteratoren verfügen nicht über dieses Merkmal, weil sie Wrapper über Delphi-Klassen mit automatisch erzeugten Headern sind; dies bedeutet, dass Sie diesen Iterator mit BCC verwenden können.
System::DynamicArray<int> a(10,20,20,30);
System::DynamicArray<int>::iterator iter = a.begin();
while (iter != a.end()) {
std::cout << *iter << std::endl;
++iter;
}
Die durch Clang erweiterten Compiler ermöglichen die Verwendung der bereichsbasierten for-Syntax:
System::DynamicArray<int> a({10,20,30,40,50});
for(int value: a) {
std::cout << value << std::endl;
}
Das Hauptmerkmal dieses Iterators besteht darin, dass er den Zugriff auf Elemente per Referenz zulässt; das bedeutet, dass Sie den Inhalt eines DynamicArray
mit einem Iterator ändern und die volle Leistung von STL-Algorithmen nutzen können.
/* This snippet uses STL Algorithms, remember to add '#include <algorithm>' at the beginning of your file */
System::DynamicArray<int> a({10,20,30,40,50});
System::DynamicArray<int>::iterator iter = a.begin();
iter[0] = -30;
// Lambdas support is Clang-only
// We can use functors in BCC
std::for_each(a.begin(),a.end(),[](int value){
std::cout << value << std::endl;
});
std::random_shuffle(a.begin(),a.end());
std::sort(a.begin(),a.end());
- Hinweis: Wenn in BCC RTTI deaktiviert ist (über IDE-Compiler-Optionen oder
#pragma
), generiert BCC E2366. Sie können die Datei compilieren, indem Sie die Iterator-Unterstützung deaktivieren. Fügen Sie diesen Code vor der ersten#include
-Direktive in die CPP-Datei ein, die den Fehler auslöst. #define NO_SYSDYN_ITERATOR
TRandomIterator::<T,E>
TRandomIterator::<T,E>
ist für jeden RTL-Container definiert, der den Integer-Indizierungsoperator E operator[ ](int)
und eine Integer-Count
-Eigenschaft implementiert. Der Hauptunterschied zu DynamicArray-Iteratoren ist, dass Sie auf Elemente nur per Referenz zugreifen können, wenn E ein Referenztyp ist. Die meisten automatisch erzeugten HPP-Header definieren operator[]
mit einem Werterückgabetyp wie TList,TStringList oder TStrings
; dies bedeutet auch, dass Sie operator->()
nicht für einen Iterator verwenden können, um auf Felder zuzugreifen, oder modifizierende STL-Algorithmen wie std::sort
verwenden können.
Da es sich hier um einen Iterator-Wrapper handelt, der außerhalb des Containers definiert ist, müssen Sie die Nicht-Member-Funktionen begin()
und end()
verwenden, um ihn zu aktivieren:
TList *foo = new TList();
auto it = begin(foo);
Die eigentliche Implementierung von begin()
und end()
ist mit ADL und SFINAE definiert. BCC wird derzeit nicht unterstützt. In der Datei sysiterator.h finden Sie weitere Details.
TEnumerableIterator<T>
TEnumerableIterator::<T>
ist für jeden Delphi-RTL-Container definiert, der die Methode GetEnumerator()
implementiert. Der zurückgegebene Aufzählungstyp muss auch die Methoden GetCurrent()
und MoveNext()
unterstützen. Dieses Muster wird in RTL-Code häufig verwendet, daher betrifft es einen Großteil von Containern. TEnumerableiterator
und TRandomITerator
sind Eingabe-Iteratoren; das bedeutet, dass sie schreibgeschützt und nur vorwärts ausgerichtet sind und mit den Nicht-Member-Funktionen begin()
und end()
implementiert werden, daher sind sie nur für Clang-basierte Compiler aktiviert. Folgende Merkmale werden unterstützt:
- Bereichsbasiertes for (EN)
- Nicht modifizierende STL-Algorithmen, die mit Eingabe-Iteratoren wie den folgenden arbeiten:
-
- std::for_each (EN)
- std::find (EN)
- Als Quelle von std::copy (EN)
Ein wichtiger Operator, der in TEnumerator
fehlt, ist der Iterator für den Abstand (std::distance); daher stehen einige Algorithmen, die mit diesem Iterator arbeiten, wie std::binary_search oder std::count, nicht zur Verfügung.
Einfügungs-Iteratoren
Bestimmte Container können nicht geändert werden, aber Sie können Elemente einfügen und entfernen, indem Sie mit dem Konzept der Einfügungs-Iteratoren (EN) Kopien von STL-Iteratoren für RTL-Container und umgekehrt erstellen. Erstellen Sie derartige Iteratoren mit den folgenden benutzerdefinierten Funktionen:
System::back_inserter<T>(T *container)
System::front_inserter<T>(T *container)
System::make_inserter<T>(T *container, size_t place)
// This code uses STL Algorithms
// Remember to '#include <algorithm>'
std::vector<UnicodeString> v{"A","B","C","D","E"};
TStringList *list = new TStringList;
TStringList *list2 = new TStringList;
std::copy(v.begin(),v.end(),back_inserter(list)); // list == A, B, C, D, E
std::copy(v.begin(),v.end(),front_inserter(list2)); // list2 == E, D, C, B, A
std::copy(v.begin(),v.end(),make_inserter(list2,1)); // list2 == E, E, D, C,B, A, D, C, B, A
std::vector<UnicodeString> filtered;
// Copy only items from list2 that equal "C"
std::copy_if(begin(list2),end(list2),std::back_inserter(filtered),[](const UnicodeString &str){
return "C" == str;
});
// filtered == C,C