Coleções (C++/CX)
Em um programa C++/CX, você pode usar gratuitamente contêineres STL (Standard Template Library) ou qualquer outro tipo de coleção definido pelo usuário. No entanto, quando você passa coleções de um lado para o outro pela ABI (interface binária do aplicativo) do Tempo de Execução do Windows — por exemplo, para um controle XAML ou para um cliente JavaScript — você deve usar tipos de coleção do Tempo de Execução do Windows.
O Tempo de Execução do Windows define as interfaces para coleções e tipos relacionados, e o C++/CX fornece as implementações concretas do C++ no arquivo de cabeçalho collection.h. Esta ilustração mostra as relações entre os tipos de coleção:
A classe Platform::Collections::Vector é semelhante à classe std::vector.
A classe Platform::Collections::Map se assemelha à classe std::map.
classe Platform::Collections::VectorView e classe Platform::Collections::MapView são versões somente leitura de
Vector
eMap
.Os iteradores são definidos no Platform::Collections Namespace. Esses iteradores satisfazem os requisitos para iteradores STL e permitem o uso de std::find, std::count_ife outros algoritmos STL em qualquer Windows::Foundation::Collections tipo de interface ou Platform::Collections tipo concreto. Por exemplo, isso significa que você pode iterar uma coleção em um componente do Tempo de Execução do Windows criado em C# e aplicar um algoritmo STL a ele.
Importante
Os iteradores de proxy
VectorIterator
eVectorViewIterator
utilizam objetos proxyVectoryProxy<T>
eArrowProxy<T>
para habilitar o uso com contêineres STL. Para obter mais informações, consulte "VectorProxy elements" mais adiante neste artigo.Os tipos de coleção C++/CX oferecem as mesmas garantias de segurança de thread que os contentores STL oferecem.
Windows::Foundation::Collections::IObservableVector e Windows::Foundation::Collections::IObservableMap definem eventos que são acionados quando a coleção muda de diferentes formas. Ao implementar essas interfaces, Platform::Collections::Map e Platform::Collections::Vetor oferecem suporte à vinculação de dados com coleções XAML. Por exemplo, se tiver um
Vector
associado a dados a umGrid
, quando adiciona um item a uma coleção, a alteração reflete-se na interface de utilizador da grelha.
Uso de vetores
Quando a sua classe tiver que passar um contêiner de sequência para outro componente do Windows Runtime, use Windows::Foundation::Collections:: IVector<T> como parâmetro ou tipo de retorno, e Platform::Collections::Vector<T> como a implementação concreta. Se você tentar usar um tipo de Vector
em um valor de retorno público ou parâmetro, o erro de compilador C3986 será gerado. Você pode corrigir o erro alterando o Vector
para um IVector
.
Importante
Se você estiver passando uma sequência dentro do seu próprio programa, use Vector
ou std::vector
porque eles são mais eficientes do que IVector
. Use IVector
apenas quando passar o container através da ABI.
O sistema do tipo Tempo de Execução do Windows não oferece suporte ao conceito de matrizes irregulares e, portanto, você não pode passar um IVector<Platform::Array<T>>
como um valor de retorno ou parâmetro de método. Para passar uma matriz irregular ou uma sequência de sequências pela ABI, use IVector<IVector<T>^>
.
Vector<T>
fornece os métodos necessários para adicionar, remover e acessar itens na coleção, e é implicitamente conversível para IVector<T>
. Você também pode usar algoritmos STL em instâncias de Vector<T>
. O exemplo a seguir demonstra algum uso básico. A função início e a função fim aqui são do namespace Platform::Collections
, não do namespace 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();
}
Se tiveres um código existente que usa std::vector
e quiseres reutilizá-lo num componente Windows Runtime, basta usar um dos construtores Vector
que recebe um std::vector
ou um par de iteradores para construir um Vector
quando passas a coleção pela ABI. O exemplo a seguir mostra como usar o construtor Vector
move para inicialização eficiente a partir de um std::vector
. Após a operação de movimentação, a variável vec
original não é mais válida.
//#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));
}
Se você tiver um vetor de cadeias de caracteres que você deve passar através da ABI em algum ponto futuro, você deve decidir se deseja criar as cadeias de caracteres inicialmente como tipos std::wstring
ou como tipos Platform::String^
. Se tiveres que fazer muito processamento nas cadeias de caracteres, usa wstring
. Caso contrário, crie as cadeias de caracteres como tipos Platform::String^
e evite o custo de convertê-las posteriormente. Você também deve decidir se deseja colocar essas cadeias de caracteres em um std:vector
ou Platform::Collections::Vector
internamente. Como prática geral, utilize std::vector
e só crie um Platform::Vector
a partir dele ao passar o contentor pelo ABI.
Tipos de valor em Vetor
Qualquer elemento a ser armazenado em um Platform::Collections::Vector deve oferecer suporte à comparação de igualdade, quer implicitamente, quer utilizando um comparador de igualdade personalizado std::equal_to que você fornece. Todos os tipos de referência e todos os tipos escalares suportam implicitamente comparações de igualdade. Para tipos de valores não escalares, como Windows::Foundation::D ateTime, ou para comparações personalizadas, por exemplo, objA->UniqueID == objB->UniqueID
—, você deve fornecer um objeto de função personalizado.
Elementos VectorProxy
Platform::Collections::VectorIterator e Platform::Collections::VectorViewIterator permitir o uso de loops de range for
e algoritmos como std::sort com um contêiner IVector<T>. Mas IVector
elementos não podem ser acessados através da desreferência de ponteiros em C++; eles podem ser acessados somente por meio dos métodos GetAt e SetAt. Portanto, esses iteradores usam as classes proxy Platform::Details::VectorProxy<T>
e Platform::Details::ArrowProxy<T>
para fornecer acesso aos elementos individuais por meio de operadores *, ->e [], conforme exigido pela Biblioteca Padrão. A rigor, dado um IVector<Person^> vec
, o tipo de *begin(vec)
é VectorProxy<Person^>
. No entanto, o objeto proxy é quase sempre transparente para o seu código. Esses objetos proxy não são documentados porque são apenas para uso interno pelos iteradores, mas é útil saber como o mecanismo funciona.
Ao utilizar um ciclo de for
baseado em intervalo em contentores IVector
, utilize auto&&
para permitir que a variável do iterador se associe corretamente aos elementos VectorProxy
. Se você usar auto&
, o aviso do compilador C4239 é gerado e VectoryProxy
é mencionado no texto de aviso.
A ilustração a seguir mostra um loop de range for
em um IVector<Person^>
. Observe que a execução é interrompida no ponto de interrupção na linha 64. A janela QuickWatch mostra que a variável iteradora p
é, na verdade, um VectorProxy<Person^>
que tem m_v
e m_i
variáveis de membro. No entanto, quando você chama GetType
nessa variável, ela retorna o tipo idêntico para a instância Person
p2
. A conclusão é que, embora VectorProxy
e ArrowProxy
possam aparecer no QuickWatch, no depurador, em certos erros do compilador ou em outros lugares, tu normalmente não precisas codificar explicitamente para eles.
Um cenário em que você precisa codificar em torno do objeto proxy é quando você precisa executar uma dynamic_cast
nos elementos — por exemplo, quando você está procurando objetos XAML de um tipo específico em uma coleção de elementos UIElement
. Nesse caso, você deve primeiro converter o elemento para Platform::Object^ e, em seguida, executar a conversão dinâmica:
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...
}
}
}
Utilização do mapa
Este exemplo mostra como inserir itens e procurá-los numa Platform::Collections::Mape, em seguida, retornar o Map
como um tipo Windows::Foundation::Collections::IMapView somente leitura.
//#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();
}
Em geral, para a funcionalidade de mapa interno, prefira o tipo std::map
por motivos de desempenho. Se você tiver que passar o contêiner através da ABI, construa um Platform::Collections::Map a partir do std::map e retorne o Map
como um Windows::Foundation::Collections::IMap. Se você tentar usar um tipo de Map
em um valor de retorno público ou parâmetro, o erro de compilador C3986 será gerado. Você pode corrigir o erro alterando o Map
para um IMap
. Em alguns casos, por exemplo, se não estiveres a fazer um grande número de consultas ou inserções e estiveres a passar a coleção pela ABI com frequência, pode ser menos dispendioso usar o Platform::Collections::Map
desde o início e evitar o custo de conversão do std::map
. Em qualquer caso, evite realizar operações de pesquisa e inserção em um IMap
, porque estas são as menos eficientes dos três tipos. Converta em IMap
somente no ponto em que você passa o contêiner pela ABI.
Tipos de valor em mapa
Os elementos em uma Platform::Collections::Map são ordenados por definição. Qualquer elemento a ser armazenado em um Map
deve suportar uma comparação de menor que com ordenação fraca estrita, seja implicitamente ou usando um comparador stl::less personalizado que você fornece. Os tipos escalares suportam a comparação implicitamente. Para tipos de valores não escalares, como Windows::Foundation::DateTime
, ou para comparações personalizadas, por exemplo, objA->UniqueID < objB->UniqueID
, você deve fornecer um comparador personalizado.
Tipos de recolha
As coleções se dividem em quatro categorias: versões modificáveis e versões somente leitura de coleções de sequências e coleções associativas. Além disso, o C++/CX aprimora as coleções fornecendo três classes iteradoras que simplificam o acesso às coleções.
Os elementos de uma coleção modificável podem ser alterados, mas os elementos de uma coleção de leitura apenas, que é conhecida como uma de exibição, só podem ser lidos. Elementos de uma Platform::Collections::Vetor ouPlatform::Collections::VectorView coleção pode ser acessada usando um iterador ou o e um índice Vetor::GetAt da coleção. Os elementos de uma coleção associativa podem ser acessados usando o Map::Lookup e uma chave da coleção.
Platform::Collections::Map class
Uma coleção modificável e associativa. Os elementos do mapa são pares chave-valor. A pesquisa de uma chave para recuperar seu valor associado e a iteração através de todos os pares chave-valor são suportadas.
Map
e MapView
são modeladas em <K, V, C = std::less<K>>
; portanto, você pode personalizar o comparador. Além disso, Vector
e VectorView
são modeladas em <T, E = std::equal_to<T>>
para que você possa personalizar o comportamento de IndexOf()
. Isso é importante principalmente para Vector
e VectorView
de estruturas de valor. Por exemplo, para criar um Vector<Windows::Foundation::DateTime>, deve fornecer um comparador personalizado porque DateTime não tem a sobrecarga do operador == .
Plataforma::Coleções::VisãoMapa classe
Uma versão somente leitura de um Map
.
Platform::Collections::Vector classe
Uma coleção de sequências modificáveis.
Vector<T>
suporta operações de acesso aleatório em tempo constante e de de tempo constante amortizado.
Platform::Collections::VectorView classe
Uma versão somente leitura de um Vector
.
Platform::Collections::InputIterator classe
Um iterador STL que satisfaz os requisitos de um iterador de entrada STL.
Platform::Collections::VectorIterator classe
Um iterador STL que cumpre os requisitos de um iterador mutável de acesso aleatório STL.
Platform::Collections::VectorViewIterator classe
Um iterador STL que satisfaz os requisitos de um iterador STL const
de acesso aleatório.
funções begin() e end()
Para simplificar o uso da STL para processar objetos de Windows::Foundation::Collections
Vector
, VectorView
, Map
, MapView
e arbitrários, o C++/CX suporta sobrecargas do iniciar a Função e Função final funções não-membros.
A tabela a seguir lista os iteradores e funções disponíveis.
Iteradores | Funções |
---|---|
Platform::Collections::VectorIterator<T> (Internamente armazena Windows::Foundation::Collections:: IVector<T> e int.) |
começar/ terminar(Windows::Foundation::Collections:: IVector<T>) |
Platform::Collections::VectorViewIterator<T> (Armazena internamente IVectorView<T>^ e int.) |
começar/ terminar (IVectorView<T>^) |
Platform::Collections::InputIterator<T> (Armazena internamente IIterator<T>^ e T.) |
começar/ terminar (IIterable<T>) |
Platform::Collections::InputIterator<IKeyValuePair<K, V>^> (Armazena internamente IIterator<T>^ e T.) |
começar/ terminar (IMap<K,V>. |
Platform::Collections::InputIterator<IKeyValuePair<K, V>^> (Armazena internamente IIterator<T>^ e T.) |
começar/ terminar (Windows::Foundation::Collections::IMapView) |
Eventos de alteração em coleções
Vector
e Map
oferecem suporte à vinculação de dados em coleções XAML implementando eventos que ocorrem quando um objeto de coleção é alterado ou redefinido, ou quando qualquer elemento de uma coleção é inserido, removido ou alterado. Você pode escrever seus próprios tipos que suportam vinculação de dados, embora não possa herdar de Map
ou Vector
porque esses tipos são selados.
Os delegados Windows::Foundation::Collections::VectorChangedEventHandler e Windows::Foundation::Collections::MapChangedEventHandler especificam as assinaturas para manipuladores de eventos de alteração de coleção. O Windows::Foundation::Collections::CollectionChange classe enum pública e Platform::Collection::Details::MapChangedEventArgs
e Platform::Collections::Details::VectorChangedEventArgs
classes ref, armazenam os argumentos de evento para determinar o que causou o evento. Os tipos de *EventArgs
são definidos no namespace Details
porque você não precisa construí-los ou consumi-los explicitamente quando usa Map
ou Vector
.
Ver também
tipo de sistema
Referência da Linguagem C++/CX
Referência a Namespaces