Prise en charge de l'itérateur C++ pour les types et conteneurs énumérables Delphi

De RAD Studio
Aller à : navigation, rechercher

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 :

Conteneurs Type d'itérateur Caractéristiques de l'itérateur Bcc Clang Type Range-for Prise en charge des <algorithmes> de la STL begin(), end()
System::DynamicArray<T> System::DynamicArray<T>::iterator random_access_iterator
Checkmark.svg
Checkmark.svg
Par référence (lecture-écriture)
Checkmark.svg
(Clang uniquement)
Complet Membres, non membres
TCollection (ex. TList) System::TRandomIterator<T,E> random_access_iterator
Checkmark.svg
Par valeur (lecture seule)
Checkmark.svg
(Clang uniquement)
Non modifiants uniquement Non membres
TEnumerable System::TEnumerableIterator<T> input_iterator
Checkmark.svg
Par valeur (lecture seule)
Checkmark.svg
(Clang uniquement)
Non modifiants , Non aléatoires Non membres
TCollection (pas TDictionary) System::TBackInsertIterator<T> back_insert_iterator
Checkmark.svg
Itérateur de sortie Ecriture uniquement (voir ci-dessous) n/a
TCollection (pas TDictionary) System::TInsertIterator<T> front_insert_iterator,insert_iterator
Checkmark.svg
Itérateur de sortie Ecriture uniquement (voir ci-dessous) n/a

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" pour System::DynamicArray<T>, comme Arrayofstring, 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 :

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

Voir aussi