Заметка
Доступ к этой странице требует авторизации. Вы можете попробовать войти в систему или изменить каталог.
Доступ к этой странице требует авторизации. Вы можете попробовать сменить директорию.
В программе C++/CX можно бесплатно использовать контейнеры стандартной библиотеки шаблонов (STL) или любой другой определяемый пользователем тип коллекции. Однако при передаче коллекций между среда выполнения Windows двоичным интерфейсом приложения (ABI), например в элемент управления XAML или клиенту JavaScript, необходимо использовать среда выполнения Windows типы коллекций.
Среда выполнения Windows определяет интерфейсы для коллекций и связанных типов, а C++/CX предоставляет конкретные реализации C++ в файле заголовка collection.h. На этой иллюстрации показаны связи между типами коллекций:
Класс
Platform::Collections::Vectorнапоминаетstd::vectorкласс.Класс
Platform::Collections::Mapнапоминаетstd::mapкласс.Platform::Collections::VectorViewкласс иPlatform::Collections::MapViewкласс — это версииVector, доступные только для чтения, иMap.Итераторы определяются в
Platform::Collectionsпространстве имен. Эти итераторы удовлетворяют требованиям для итераторов STL и позволяют использоватьstd::findstd::count_ifи другие алгоритмы STL для любогоWindows::Foundation::Collectionsтипа интерфейса илиPlatform::Collectionsконкретного типа. Например, это означает, что можно выполнить итерацию коллекции в компоненте среда выполнения Windows, созданном в C# и применить к нему алгоритм STL.Important
Итераторы прокси-сервера
VectorIteratorиVectorViewIteratorиспользуют прокси-объектыVectorProxy<T>иArrowProxy<T>для включения использования с контейнерами STL. Для получения дополнительной информации см. элемент VectorProxy далее в этой статье.Типы коллекций C++/CX поддерживают ту же безопасность потоков, что и контейнеры STL.
Windows::Foundation::Collections::IObservableVectorиWindows::Foundation::Collections::IObservableMapопределяют события, которые запускаются при изменении коллекции различными способами. Реализуя эти интерфейсы,Platform::Collections::MapиPlatform::Collections::Vectorподдерживают привязку данных с помощью коллекций XAML. Например, если имеется объектVector, данные которого связаны сGrid, то при добавлении данных в коллекцию их изменения отражаются в пользовательском интерфейсе таблицы.
Vector usage
Когда класс должен передать контейнер последовательности другому компоненту среды выполнения Windows, используйте Windows::Foundation::Collections::IVector<T> его в качестве параметра или возвращаемого типа, а Platform::Collections::Vector<T> также в качестве конкретной реализации. При попытке использования типа Vector в качестве открытого возвращаемого значения или параметра возникнет ошибка компилятора C3986. Эту ошибку можно исправить, заменив Vector объектом IVector.
Important
В случае передачи последовательности внутри разрабатываемой программы используйте Vector или std::vector , поскольку они более эффективны по сравнению с IVector. Используйте IVector только при передаче контейнера с помощью ABI.
Система типов среда выполнения Windows не поддерживает концепцию сорных массивов, поэтому нельзя передать IVector<Platform::Array<T>> в качестве возвращаемого значения или параметра метода. Для передачи массива массивов или последовательности массивов в ABI используйте IVector<IVector<T>^>.
КлассVector<T> предоставляет методы, необходимые для добавления и удаления элементов коллекции и доступа к ним. Его можно неявно преобразовать в класс IVector<T>. Алгоритмы STL также можно применять к экземплярам Vector<T>. В следующем примере демонстрируются некоторые простейшие варианты использования. Функция begin иend функция здесь находятся из Platform::Collections пространства имен, а не 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();
}
Если у вас есть существующий код, который используется std::vector и вы хотите повторно использовать его в компоненте среда выполнения Windows, просто используйте один из Vector конструкторов, которые принимают std::vector или пару итераторов, чтобы создать в Vector точке, где вы передаете коллекцию через ABI. В следующем примере показано использование конструктора класса Vector для эффективной инициализации из объекта std::vector. После операции перемещения исходная переменная vec более не является допустимой.
//#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));
}
Если имеется вектор строк, которые должны будут передаваться через интерфейс ABI, необходимо решить, следует ли изначально создавать строки как типы std::wstring или как типы Platform::String^ . Если предполагается выполнение большого объема операций с этими строками, используйте тип wstring. В противном случае создайте строки типа Platform::String^ , чтобы избежать издержек, связанных с их последующим преобразованием. Кроме того, необходимо определить, куда лучше поместить строки для внутреннего использования — в std::vector или в Platform::Collections::Vector . В общем случае рекомендуется использовать объект std::vector и создавать из него Platform::Vector только при передаче контейнера через интерфейс ABI.
Типы значений в объекте Vector
Любой элемент, хранящийся в объекте Platform::Collections::Vector, должен поддерживать сравнение равенства либо неявно, либо с помощью предоставленного пользовательского std::equal_to компаратора. Все ссылочные типы и все скалярные типы неявно поддерживают сравнение на равенство. Для не скалярных типов значений, таких как Windows::Foundation::DateTime, или для пользовательских сравнений, например objA->UniqueID == objB->UniqueID, необходимо предоставить пользовательский объект функции.
VectorProxy elements
Platform::Collections::VectorIterator и Platform::Collections::VectorViewIterator позволяют использовать циклы и алгоритмы, такие как range for с контейнером IVector<T>. Но элементы IVector нельзя получить доступ через разыменовку указателя C++, их можно получить доступ только через методы GetAt и методы SetAt. Таким образом, эти итераторы используют прокси-классы Platform::Details::VectorProxy<T> и Platform::Details::ArrowProxy<T>, предоставляя доступ к отдельным элементам через *, -> и [] операторы, как это требуется Стандартной библиотекой. Строго говоря, при использовании IVector<Person^> vecтипом *begin(vec) является VectorProxy<Person^>. Однако прокси-объект практически всегда прозрачен для кода. Эти прокси-объекты не документируются, поскольку предназначены исключительно для внутреннего пользования итераторами, однако полезно иметь представление о самом механизме работы.
При использовании цикла на основе for диапазона по IVector контейнерам используйте auto&& для правильной привязки переменных итератора к VectorProxy элементам. При использовании auto&возникает предупреждение компилятора C4239 и VectorProxy упоминается в тексте предупреждения.
На следующем рисунке показан цикл range for с контейнерами IVector<Person^>. Обратите внимание, что выполнение прекращается в точке останова на строке 64. В окне QuickWatch показывается, что переменная итератора p на самом деле является VectorProxy<Person^>, у которого есть переменные-члены m_v и m_i. Однако при вызове GetType для этой переменной она возвращает идентичный тип в экземпляр Personp2. Вывод заключается в том, что хотя VectorProxy и ArrowProxy может отображаться в QuickWatch, отладчик некоторых ошибок компилятора или других местах, вам обычно не нужно явно кодировать для них.
Один из сценариев, в котором необходимо создать код для прокси-объекта, заключается в следующем: необходимо выполнить операцию dynamic_cast с элементами, например при поиске объектов XAML определенного типа в коллекции элементов UIElement . В этом случае необходимо сначала привести элемент к Platform::Object^, а затем выполнить динамическое приведение типа.
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...
}
}
}
Map usage
В этом примере показано, как вставлять элементы и искать их в объекте Platform::Collections::Map, а затем возвращать этот Map как тип Windows::Foundation::Collections::IMapView только для чтения.
//#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();
}
Как правило, для реализации внутренних возможностей сопоставления предпочтительно использовать тип std::map (из соображений производительности). Если вам необходимо передать контейнер через ABI, создайте Platform::Collections::Map из std::map и верните Map как Windows::Foundation::Collections::IMap. При попытке использования типа Map в качестве открытого возвращаемого значения или параметра возникнет ошибка компилятора C3986. Эту ошибку можно исправить, заменив Map объектом IMap. В некоторых случаях (например, если вы не выполняете большого количества операций поиска или вставки и часто передаете коллекцию через интерфейс ABI) более рационально использовать класс Platform::Collections::Map с самого начала, не затрачивая ресурсы на преобразование типа объекта std::map. В любом случае следует избегать операций поиска и вставки в объектах IMap , поскольку из всех трех типов он обладает самой низкой производительностью. Преобразование в IMap следует выполнять только в момент передачи контейнера через интерфейс ABI.
Типы значений в объекте Map
Элементы в объекте Platform::Collections::Map упорядочены. Любой элемент, хранящийся в Map, должен поддерживать сравнение на меньше со строгим слабым упорядочением, либо неявно, либо с помощью предоставленного настраиваемого std::less компаратора. Скалярные типы поддерживают сравнение неявно. Для нескалярных типов значений, таких как Windows::Foundation::DateTime, или для пользовательских вариантов сравнения (например, objA->UniqueID < objB->UniqueID) необходимо определять специальный алгоритм сравнения.
Collection types
Коллекции подразделяются на четыре категории: изменяемые и доступные только для чтения версии последовательных и ассоциативных коллекций. Кроме того, C++/CX улучшает коллекции, предоставляя три класса итератора, упрощающие доступ к коллекциям.
Элементы модифицируемой коллекции могут быть изменены, но элементы коллекции только для чтения, которая называется представлением, можно только прочитать. Элементы Platform::Collections::Vector или Platform::Collections::VectorView коллекции можно обработать с помощью итератора и индекса коллекции Vector::GetAt. К элементам ассоциативной коллекции можно обращаться, используя коллекцию Map::Lookup и ключ.
Platform::Collections::Map Класс
Изменяемая ассоциативная коллекция. Элементы объекта Map представляют собой пары "ключ-значение". Поддерживается как поиск значения по связанному с ним ключу, так и перебор всех пар "ключ-значение".
В классахMap и MapView используется шаблон <K, V, C = std::less<K>>; таким образом, алгоритм сравнения можно изменять. Кроме того, в классах Vector и VectorView используется шаблон <T, E = std::equal_to<T>> , поэтому поведение метода IndexOf()можно изменять. Это важно в основном для объектов Vector и VectorView , содержащих структуры значения. Например, чтобы создать Vector<Windows::Foundation::DateTime> объект, необходимо предоставить пользовательский компаратор, так как DateTime не перегружает == оператор.
Platform::Collections::MapView Класс
Версия объекта Mapтолько для чтения.
Platform::Collections::Vector Класс
Изменяемая коллекция последовательностей.
Vector<T> поддерживает случайный доступ с постоянной временной сложностью и операции с амортизированной временной сложностью Append.
Platform::Collections::VectorView Класс
Версия объекта Vectorтолько для чтения.
Platform::Collections::InputIterator Класс
Итератор STL, отвечающий требованиям итератора ввода STL.
Platform::Collections::VectorIterator Класс
Итератор STL, отвечающий требованиям изменяемого итератора произвольного доступа STL.
Platform::Collections::VectorViewIterator Класс
Итератор STL, удовлетворяющий требованиям итератора случайного доступа STL const .
Функции begin() и end()
Чтобы упростить использование STL для обработки Vector, VectorView, Map, MapView и произвольных Windows::Foundation::Collections объектов, C++/CX поддерживает перегрузки функций begin и end, которые являются немемберными.
В следующей таблице перечислены все доступные итераторы и функции.
| Iterators | Functions |
|---|---|
Platform::Collections::VectorIterator<T>(Внутренне хранит Windows::Foundation::Collections::IVector<T> и int.) |
begin
/
end(Windows::Foundation::Collections::IVector<T>) |
Platform::Collections::VectorViewIterator<T>(Внутренние хранилища IVectorView<T>^ и int.) |
begin
/
end (IVectorView<T>^) |
Platform::Collections::InputIterator<T>(Внутренне хранит IIterator<T>^ и T.) |
begin
/
end (IIterable<T>) |
Platform::Collections::InputIterator<IKeyValuePair<K, V>^>(Внутренние хранилища IIterator<T>^ и T.) |
begin
/
end (IMap<K,V>) |
Platform::Collections::InputIterator<IKeyValuePair<K, V>^>(Внутренне хранит IIterator<T>^ и T.) |
begin
/
end (Windows::Foundation::Collections::IMapView) |
События изменения коллекций
КлассыVector и Map поддерживают привязку данных в коллекциях XAML за счет реализации событий, которые возникают при изменении или сбросе объекта коллекции, а также при вставке, удалении или изменении любого элемента коллекции. Можно разрабатывать собственные типы, поддерживающие привязку данных, но нельзя наследовать от типов Map и Vector , так как эти типы запечатаны.
Windows::Foundation::Collections::VectorChangedEventHandler и Windows::Foundation::Collections::MapChangedEventHandler делегаты указывают сигнатуры для обработчиков событий для событий изменения коллекции. Публичный Windows::Foundation::Collections::CollectionChange класс перечисления и Platform::Collections::Details::MapChangedEventArgs и Platform::Collections::Details::VectorChangedEventArgs ref классы хранят аргументы событий, чтобы определить, что вызвало событие.
*EventArgs Типы определяются в Details пространстве имен, так как вам не нужно создавать или использовать их явным образом при использовании Map илиVector.