Collections (C++/CX)
Dans un programme C++/CX, vous pouvez utiliser librement les conteneurs de la bibliothèque standard de modèles (STL) ou tout autre type de collection défini par l’utilisateur. Cependant, lorsque vous passez des collections d’un côté à l’autre de l’interface binaire des applications Windows Runtime (ABI) — par exemple, à un contrôle XAML ou à un client JavaScript — vous devez utiliser des types de collections Windows Runtime.
Windows Runtime définit les interfaces pour les collections et les types associés, et C++/CX fournit les implémentations C++ concrètes dans le fichier d’en-tête collection.h. Cette illustration montre les relations entre les types de collection :
La classe Platform::Collections::Vector ressemble à la classe std::vector.
La classe Platform::Collections::Map ressemble à la classe std::map.
Les classes Platform::Collections::VectorView et Platform::Collections::MapView sont des versions en lecture seule de
Vector
etMap
.Les itérateurs sont définis dans Platform::Collections Namespace. Ces itérateurs répondent aux spécifications des itérateurs STL et permettent d’utiliser std::find, std::count_ifet d’autres algorithmes STL sur n’importe quel type d’interface Windows::Foundation::Collections ou type concret Platform::Collections . Par exemple, cela signifie que vous pouvez itérer une collection dans un composant Windows Runtime créé en C# et y appliquer un algorithme STL.
Important
Les itérateurs de proxy
VectorIterator
etVectorViewIterator
utilisent les objets proxyVectoryProxy<T>
etArrowProxy<T>
pour activer l'utilisation avec des conteneurs STL. Pour plus d'informations, consultez « Éléments VectorProxy » dans la suite de cet article.Les types de collections C++/CX prennent en charge les mêmes garanties de sécurité des threads que les conteneurs STL.
Windows::Foundation::Collections::IObservableVector et Windows::Foundation::Collections::IObservableMap définissent des événements qui sont déclenchés quand la collection est modifiée de différentes manières. En implémentant ces interfaces, Platform::Collections::Map et Platform::Collections::Vector prennent en charge la liaison de données avec les collections XAML. Par exemple, si vous avez un vecteur
Vector
qui est lié aux données à unGrid
, lorsque vous ajoutez un élément à une collection, la modification est répercutée dans la grille de l'interface utilisateur.
Utilisation de Vector
Lorsque votre classe doit passer un conteneur de séquences à un autre composant Windows Runtime, utilisez Windows::Foundation::Collections::IVector<T> comme paramètre ou type de retour, et Platform::Collections::Vector<T> comme implémentation concrète. Si vous tentez d'utiliser un type Vector
dans une valeur ou un paramètre de retour, l'erreur de compilateur C3986 est générée. Vous pouvez corriger l'erreur en remplaçant le Vector
par un IVector
.
Important
Si vous passez une séquence dans le cadre de votre propre programme, utilisez Vector
ou std::vector
car ils sont plus efficaces que IVector
. Utilisez IVector
uniquement lorsque vous passez le conteneur à travers l'ABI.
Le système de types Windows Runtime ne prend pas en charge le concept de tableaux irréguliers et, par conséquent, vous ne pouvez pas passer un IVector<Platform::Array<T>>
comme valeur de retour ou paramètre de méthode. Pour passer un tableau en escalier ou une séquence de séquences à travers l'ABI, utilisez IVector<IVector<T>^>
.
Vector<T>
fournit les méthodes requises pour ajouter, supprimer les éléments et y accéder dans la collection, et il est implicitement convertible en IVector<T>
. Vous pouvez également utiliser les algorithmes STL sur les instances de Vector<T>
. L'exemple ci-dessous illustre l'utilisation de base. Les fonctions begin et end sont issues ici de l'espace Platform::Collections
au lieu de l'espace std
.
#include <collection.h>
#include <algorithm>
using namespace Platform;
using namespace Platform::Collections;
using namespace Windows::Foundation::Collections;
void Class1::Test()
{
Vector<int>^ vec = ref new Vector<int>();
vec->Append(1);
vec->Append(2);
vec->Append(3);
vec->Append(4);
vec->Append(5);
auto it =
std::find(begin(vec), end(vec), 3);
int j = *it; //j = 3
int k = *(it + 1); //or it[1]
// Find a specified value.
unsigned int n;
bool found = vec->IndexOf(4, &n); //n = 3
// Get the value at the specified index.
n = vec->GetAt(4); // n = 3
// Insert an item.
// vec = 0, 1, 2, 3, 4, 5
vec->InsertAt(0, 0);
// Modify an item.
// vec = 0, 1, 2, 12, 4, 5,
vec->SetAt(3, 12);
// Remove an item.
//vec = 1, 2, 12, 4, 5
vec->RemoveAt(0);
// vec = 1, 2, 12, 4
vec->RemoveAtEnd();
// Get a read-only view into the vector.
IVectorView<int>^ view = vec->GetView();
}
Si vous avez du code existant qui utilise std::vector
et que vous souhaitez le réutiliser dans un composant Windows Runtime, utilisez simplement l’un des constructeurs Vector
qui prend un std::vector
ou une paire d’itérateurs pour construire un Vector
au point où vous passez la collection à travers l’ABI. L'exemple ci-dessous indique comment utiliser le constructeur de déplacement Vector
pour une initialisation efficace à partir d'un std::vector
. Une fois l'opération de déplacement terminée, la variable vec
d'origine n'est plus valide.
//#include <collection.h>
//#include <vector>
//#include <utility> //for std::move
//using namespace Platform::Collections;
//using namespace Windows::Foundation::Collections;
//using namespace std;
IVector<int>^ Class1::GetInts()
{
vector<int> vec;
for(int i = 0; i < 10; i++)
{
vec.push_back(i);
}
// Implicit conversion to IVector
return ref new Vector<int>(std::move(vec));
}
Si vous avez un vecteur de chaînes que vous devez passer à travers l'ABI à un futur point, vous devez décider s'il faut créer des chaînes initialement en tant que types std::wstring
ou Platform::String^
. Si vous devez effectuer un important traitement sur les chaînes, utilisez wstring
. Sinon, créez les chaînes en tant que types Platform::String^
et évitez ainsi d'avoir à les convertir ultérieurement. Vous devez également décider s'il faut placer ces chaînes dans std:vector
ou Platform::Collections::Vector
en interne. De manière générale, utilisez std::vector
et créez ensuite Platform::Vector
à partir de ce dernier uniquement lorsque vous passez le conteneur à travers l'ABI.
Types de valeur relatifs au vecteur
Tout élément à stocker dans Platform::Collections::Vector doit prendre en charge la comparaison d'égalité, implicitement ou à l'aide d'un comparateur std::equal_to personnalisé que vous fournissez. Tous les types de références et tous les types scalaires prennent en charge implicitement les comparaisons d'égalité. Pour les types de valeurs non scalaires tels que Windows::Foundation::DateTime, ou pour les comparaisons personnalisées, par exemple, objA->UniqueID == objB->UniqueID
, vous devez fournir un objet de fonction personnalisé.
Éléments VectorProxy
Platform::Collections::VectorIterator et Platform::Collections::VectorViewIterator permettent l’utilisation de boucles range for
et d’algorithmes comme std::sort avec un conteneur IVector<T>. Toutefois, les éléments IVector
ne sont pas accessibles par l’intermédiaire du déréférencement de pointeur C++. Ils sont accessibles uniquement avec les méthodes GetAt et SetAt . Par conséquent, ces itérateurs utilisent les classes proxy Platform::Details::VectorProxy<T>
et Platform::Details::ArrowProxy<T>
pour fournir un accès aux éléments individuels via les opérateurs *, -> et [], comme l’exige la bibliothèque standard. À proprement parler, avec un IVector<Person^> vec
, le type de *begin(vec)
est VectorProxy<Person^>
. Toutefois, l'objet proxy est presque toujours transparent pour votre code. Ces objets proxy ne sont pas documentés car ils servent uniquement à un usage interne par les itérateurs, mais il est utile de savoir comment le mécanisme fonctionne.
Lorsque vous utilisez une boucle basée sur une plage for
sur des conteneurs IVector
, utilisez auto&&
pour permettre à la variable itérateur de se lier correctement aux éléments VectorProxy
. Si vous utilisez auto&
, l’avertissement du compilateur C4239 est levé et VectoryProxy
est mentionné dans le texte de l’avertissement.
L'illustration suivante montre une boucle range for
sur un IVector<Person^>
. Notez que l'exécution est interrompue sur le point d'arrêt à la ligne 64. La fenêtre Espion express indique que la variable d'itérateur p
est en fait un VectorProxy<Person^>
qui a les variables membres m_v
et m_i
. Toutefois, lorsque vous appelez la méthode GetType
sur cette variable, elle retourne le type identique à l'instance Person
p2
. Le principal avantage est que, bien que VectorProxy
et ArrowProxy
puissent apparaître dans Espion express, le débogueur de certaines erreurs de compilateur, il n'est pas nécessaire en général de coder explicitement pour eux.
Un scénario dans lequel vous devez coder autour de l'objet proxy est lorsque vous devez effectuer un dynamic_cast
sur les éléments, par exemple lorsque vous recherchez des objets XAML d'un type particulier dans une collection d'éléments UIElement
. Dans ce cas, vous devez commencer par caster l'élément en Platform::Objectpuis effectuer le cast dynamique :
void FindButton(UIElementCollection^ col)
{
// Use auto&& to avoid warning C4239
for (auto&& elem : col)
{
Button^ temp = dynamic_cast<Button^>(static_cast<Object^>(elem));
if (nullptr != temp)
{
// Use temp...
}
}
}
Utilisation de Map
Cet exemple montre comment insérer des éléments et les consulter dans Platform::Collections::Map, puis retourner Map
sous forme d’un type Windows::Foundation::Collections::IMapView en lecture seule.
//#include <collection.h>
//using namespace Platform::Collections;
//using namespace Windows::Foundation::Collections;
IMapView<String^, int>^ Class1::MapTest()
{
Map<String^, int>^ m = ref new Map<String^, int >();
m->Insert("Mike", 0);
m->Insert("Dave", 1);
m->Insert("Doug", 2);
m->Insert("Nikki", 3);
m->Insert("Kayley", 4);
m->Insert("Alex", 5);
m->Insert("Spencer", 6);
// PC::Map does not support [] operator
int i = m->Lookup("Doug");
return m->GetView();
}
En général, pour les fonctionnalités de carte intégrées, préférez le type std::map
pour des raisons de performance. Si vous devez passer le conteneur à travers l’ABI, construisez un Platform::Collections::Map à partir de std::map et retournez le Map
sous forme de Windows::Foundation::Collections::IMap. Si vous tentez d'utiliser un type Map
dans une valeur ou un paramètre de retour, l'erreur de compilateur C3986 est générée. Vous pouvez corriger l'erreur en remplaçant le Map
par un IMap
. Dans certains cas, par exemple si vous n'effectuez pas un grand nombre de recherches ou d'insertions et que vous passez fréquemment la collection à travers l'ABI, il peut être moins coûteux d'utiliser Platform::Collections::Map
et d'éviter ainsi le coût de conversion de std::map
. Dans tous les cas, évitez les recherches et insertions sur un IMap
, car c'est le moins performant des trois types. Effectuez une conversion en IMap
uniquement au point où vous passez le conteneur à travers l'ABI.
Types de valeur relatifs au mappage
Les éléments contenus dans Platform::Collections::Map sont classés. Tout élément à stocker dans Map
doit prendre en charge la comparaison « inférieur à » avec le classement faible strict, implicitement ou à l'aide d'un comparateur personnalisé stl::less que vous fournissez. Les types scalaires prennent en charge la comparaison implicitement. Pour les types de valeurs non scalaires tels que Windows::Foundation::DateTime
, ou pour les comparaisons personnalisées, par exemple, objA->UniqueID < objB->UniqueID
, vous devez fournir un comparateur personnalisé.
Types de collections
Les collections sont classées en quatre catégories : versions modifiables et versions en lecture seule des collections séquentielles et associatives. De plus, C++/CX améliore les collections en fournissant trois classes d’itérateurs qui simplifient l’accès aux collections.
Les éléments d'une collection modifiable peuvent être modifiés, mais les éléments d'une collection en lecture seule, appelée vue, peuvent uniquement être lus. Les éléments d’une collection Platform::Collections::Vector ou Platform::Collections::VectorView peuvent être accessibles à l’aide d’un itérateur ou via la méthode Vector::GetAt de la collection et un index. Les éléments d’une collection associative peuvent être accessibles via la méthode Map::Lookup de la collection et une clé.
Platform::Collections::Map, classe
Collection associative modifiable. Les éléments de mappage sont des paires clé/valeur. La recherche d'une clé pour récupérer sa valeur associée et l'itération sur toutes les paires clé/valeur sont toutes deux prises en charge.
Map
et MapView
sont basés sur un modèle de <K, V, C = std::less<K>>
; vous pouvez donc personnaliser le comparateur. En outre, Vector
et VectorView
sont basés sur des modèles de <T, E = std::equal_to<T>>
pour vous permettre de personnaliser le comportement de IndexOf()
. C'est important principalement pour le Vector
et le VectorView
des structures de valeur. Par exemple, pour créer un Vector<Windows::Foundation::DateTime>, vous devez fournir un comparateur personnalisé, car DateTime ne surcharge pas l’opérateur ==.
Platform::Collections::MapView, classe
Version en lecture seule d'un Map
.
Platform::Collections::Vector, classe
Collection de séquence modifiable. Vector<T>
prend en charge les opérations d'accès aléatoire en temps constant et les opérations d' ajout en temps constant amorti.
Platform::Collections::VectorView, classe
Version en lecture seule d'un Vector
.
Platform::Collections::InputIterator, classe
Itérateur STL qui satisfait aux spécifications d'un itérateur d'entrée STL.
Platform::Collections::VectorIterator, classe
Itérateur STL qui répond aux spécifications d'un itérateur à accès aléatoire mutable STL.
Platform::Collections::VectorViewIterator, classe
Un itérateur STL qui satisfait aux exigences d’un itérateur const
à accès aléatoire STL.
Fonctions begin() et end()
Pour simplifier l’utilisation de la STL pour traiter Vector
, VectorView
, Map
, MapView
et des objets Windows::Foundation::Collections
arbitraires, C++/CX prend en charge les surcharges des fonctions non-membres begin Function et end Function.
Le tableau ci-dessous répertorie les itérateurs et fonctions disponibles.
Itérateurs | Functions |
---|---|
Platform::Collections::VectorIterator<T> (Stocke en interne Windows::Foundation::Collections::IVector<T> et un int.) |
begin/ end(Windows::Foundation::Collections::IVector<T>) |
Platform::Collections::VectorViewIterator<T> (Stocke en interne IVectorView<T>^ et un int.) |
begin/ end (IVectorView<T>^) |
Platform::Collections::InputIterator<T> (Stocke en interne IIterator<T>^ et T.) |
begin/ end (IIterable<T>) |
Platform::Collections::InputIterator<IKeyValuePair<K, V>^> (Stocke en interne IIterator<T>^ et T.) |
begin/ end (IMap<K,V>). |
Platform::Collections::InputIterator<IKeyValuePair<K, V>^> (Stocke en interne IIterator<T>^ et T.) |
begin/ end (Windows::Foundation::Collections::IMapView) |
Événements de modification de collection
Vector
et Map
prennent en charge la liaison des données dans les collections XAML en implémentant des événements qui se produisent lorsqu'un objet de collection est changé ou réinitialisé, ou lorsque l'élément d'une collection est inséré, supprimé ou modifié. Vous pouvez écrire vos propres types qui prennent en charge la liaison de données, bien que vous ne puissiez pas hériter de Map
ou de Vector
car ces types sont verrouillés.
Les délégués Windows::Foundation::Collections::VectorChangedEventHandler et Windows::Foundation::Collections::MapChangedEventHandler spécifient les signatures des gestionnaires d’événements pour les événements de modification de collection. La classe d’énumération publique Windows::Foundation::Collections::CollectionChange , ainsi que les classes ref Platform::Collection::Details::MapChangedEventArgs
et Platform::Collections::Details::VectorChangedEventArgs
stockent les arguments d’événement pour déterminer ce qui a déclenché l’événement. Les types *EventArgs
sont définis dans l’espace de noms Details
car vous n’avez pas besoin de les construire ou de les consommer explicitement lorsque vous utilisez Map
ou Vector
.
Voir aussi
Système de type
Informations de référence sur le langage C++/CX
Référence aux espaces de noms