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.
- Remarque : TDictionary peut avoir un indice mais n'autorise pas les accès aléatoires. C'est un TEnumerable.
- 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 de DynamicArray<T>
. En conséquence, il implémente begin()
et end()
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());
- Remarque : Si RTTI est désactivé dans BCC (via les options du compilateur de l'EDI ou par
#pragma
), BCC génère E2366. Vous pouvez compiler le fichier en désactivant la prise en charge de l'itérateur. Ajoutez ce code avant n'importe quelle directive#include
dans le fichier .cpp qui déclenche l'erreur. #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'entier E 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éfinissent operator[]
avec un type de valeur de retour tel que TList,TStringList ou TStrings
. Cela signifie également que vous ne pouvez pas utiliser operator->()
sur un itérateur pour accéder à des champs ou utiliser les algorithmes STL de modification tels que std::sort
.
Comme c'est un wrapper d'itérateur défini à l'extérieur du conteneur, vous devez utiliser les begin()
et end()
non membres pour l'activer :
TList *foo = new TList();
auto it = begin(foo);
L'implémentation réelle de begin()
et end()
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éthode GetEnumerator()
. Le type Enumerator renvoyé doit aussi prendre en charge les méthodes GetCurrent()
et MoveNext()
. Ce modèle est fréquemment utilisé dans le code RTL, et contient une grande quantité de conteneurs. TEnumerableiterator
et TRandomITerator
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 des begin()
et end()
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.
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