Prise en charge de l'itérateur C++ pour les types et conteneurs énumérables Delphi
Remonter à Prise en charge du langage pour les bibliothèques RAD Studio (C++)
Cette page décrit la prise en charge de l'itérateur C++ en cours pour les conteneurs et les types énumérables Delphi. Le tableau suivant récapitule les types et les conteneurs pris en charge :
Sommaire
Recommandations
La plupart des itérateurs sont définis par le système, et sont sélectionnés par le compilateur via ADL et SFINAE en tant que modèles. Cela signifie qu'ils fonctionnent pour la majorité des types, mais les interfaces inhabituelles ou le comportement au sein de vos propres types peuvent nécessiter d'écrire un itérateur.Par exemple, TDictionary, bien qu'il soit énumérable, ne prend pas en charge l'accès aléatoire à un index et ne peut donc pas utiliser random_access_iterator. Son propre itérateur est défini. Les recommandations suivantes peuvent être utilisées comme règles de base pour définir quels itérateurs sont disponibles pour un type.
- Si le type a uniquement une méthode
GetEnumerator()
, vous pouvez utiliser Range-for et un ensemble limité d'algorithmes de la STL en lecture seule. - Si le type a uniquement un indice
operator[]
, vous pouvez utiliser Range-for et tous les algorithmes de la STL en lecture seule.
- Si le type est une sorte de
System::DynamicArray<T>
, vous pouvez utiliser Range-for et l'ensemble complet d'algorithmes de la STL. Gardez à l'esprit que de nombreux types RTL sont des "alias" pourSystem::DynamicArray<T>
, commeArrayofstring
,TIntegerDynArray
,TStringDynArray
, et de nombreux autres.
DynamicArray<T>::iterator
DynamicArray<T>::iterator
est défini sous forme de type interne deDynamicArray<T>
. En conséquence, il implémentebegin()
etend()
en tant que fonctions membre. Le reste des itérateurs pris en charge ne comporte pas cette fonctionnalité car ils sont des wrappers de classes Delphi ayant des en-têtes auto-générés. Ce qui signifie que vous pouvez utiliser cet itérateur avec BCC.
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;
}
Les compilateurs améliorés par Clang vous permettent d'utiliser la syntaxe range-for :
System::DynamicArray<int> a({10,20,30,40,50});
for(int value: a) {
std::cout << value << std::endl;
}
La fonctionnalité principale de cet itérateur est qu'il vous permet d'accéder aux éléments par référence, cela signifie que vous pouvez modifier le contenu d'un DynamicArray
en utilisant un itérateur et avoir accès à la puissance des algorithmes de la STL.
/* 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());
Modèle:Remarque
#define NO_SYSDYN_ITERATOR
TRandomIterator::<T,E>
TRandomIterator::<T,E>
est défini pour tout conteneur RTL qui implémente l'opérateur d'indice d'entierE operator[ ](int)
et la propriétéCount
d'un entier. La principale différence avec les itérateurs DynamicArray est que vous pouvez uniquement accéder aux éléments par référence si E est un type de référence. La plupart des en-têtes .hpp auto-générés définissentoperator[]
avec un type de valeur de retour tel queTList,TStringList ou TStrings
. Cela signifie également que vous ne pouvez pas utiliseroperator->()
sur un itérateur pour accéder à des champs ou utiliser les algorithmes STL de modification tels questd::sort
.
Comme c'est un wrapper d'itérateur défini à l'extérieur du conteneur, vous devez utiliser lesbegin()
etend()
non membres pour l'activer :
TList *foo = new TList();
auto it = begin(foo);
L'implémentation réelle debegin()
etend()
est définie en utilisant ADL et SFINAE. BCC n'est pas actuellement pris en charge. Consultez l'en-tête sysiterator.h pour plus de détails.
TEnumerableIterator<T>
TEnumerableIterator::<T>
est défini pour chaque conteneur RTL Delphi qui implémente la méthodeGetEnumerator()
. Le type Enumerator renvoyé doit aussi prendre en charge les méthodesGetCurrent()
etMoveNext()
. Ce modèle est fréquemment utilisé dans le code RTL, et contient une grande quantité de conteneurs.TEnumerableiterator
etTRandomITerator
sont des itérateurs d'entrée (EN); ce qui signifie qu'ils sont read-only et forward-only et sont implémentés en utilisant desbegin()
etend()
non membres. Ils sont donc uniquement activés par les compilateurs améliorés par Clang. Les fonctionnalités suivantes sont prises en charge :
- Range-for
- Des algorithmes de la STL non modifiants qui agissent sur des itérateurs d'entrée comme :
-
- std::for_each
- std::find
- En tant que source de std::copy
Le principal opérateur faisant défaut à TEnumerator
est la différence entre deux itérateurs (std::distance). Ainsi, certains algorithmes tels que std::binary_search ou std::count basés sur la distance entre itérateurs ne sont pas disponibles.
Concernant les types énumérateurs de collection, RAD Studio définit formellement le statut de l'énumérateur lorsque l'itération est achevée : “Le statut de l'énumérateur n'est pas valide lorsque MoveNext renvoie False ; l'énumérateur doit être libéré ou re-créé et ne doit plus être accessible”.
Itérateurs d'insertion
Bien que vous ne puissiez pas modifier certains conteneurs sur place, vous pouvez insérer ou supprimer de nouveaux éléments en utilisant le concept des itérateurs d'insertion (EN) pour effectuer des copies à partir des itérateurs STL vers les conteneurs RTL et vice versa. Utilisez les fonctions personnalisées suivantes pour créer ces itérateurs :
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