Общая функция для преобразования варианта SAFEARRAY в контейнеры STL

У меня есть некоторые функции, которые я использую для преобразования 2D-варианта SAFEARRAY в различные контейнеры STL, вроде как (только для иллюстрации)

template<typename T>
std::set<T> SetFromSafeArray(VARIANT srcArray)
{
CComSafeArray<T> srcComArray(srcArray.parray);
std::set<T> destContainer;

for (ULONG i=0;i<srcComArray.GetCount();++i)
destContainer.insert(srcComArray.GetAt(i));

return destContainer;
}

Я чувствую, что это не очень подходящий для C ++ способ, и это означает, что для каждого контейнера STL, в который я конвертирую, есть отдельная функция.

Моя идея заключалась в том, чтобы написать оболочку и пользовательский итератор для CComSafeArrays, чтобы я мог просто сделать …

std::copy(srcComArray.begin(), srcComArray.end(), destContainer.begin());

но никогда прежде не писал итератор и, будучи новичком, не знаю, будет ли это легко.

Является ли пользовательский итератор CComSafeArray моим лучшим, стандартным вариантом, похожим на c ++ (в этом случае я уверен, что смогу найти хорошее руководство по написанию итератора)? Или есть какой-то другой способ сделать это?

Повышение не вариант.

ТИА

5

Решение

Моя идея заключалась в том, чтобы написать оболочку и пользовательский итератор для CComSafeArrays

Это очень хорошая идея для создания итератора, но вам не нужна оболочка CComSafeArray<T>нужен только итератор.

так что я мог просто сделать …

std::copy(srcComArray.begin(), srcComArray.end(), destContainer.begin());

Но вместо того, чтобы идти своим путем, вы можете сделать это:

SomeContainer<T> destContainer(begin(srcComArray), end(srcComArray));

Потому что почти у каждого контейнера STL есть конструктор из диапазона (пара итераторов).

Предполагая, что вы написали итератор CComSafeArray<T> — функции begin / end будут такими:

template <typename T>
CComSafeArrayIterator<T> begin(CComSafeArray<T>& container)
{
return CComSafeArrayIterator<T>(container, 0);
}
template <typename T>
CComSafeArrayIterator<T> end(CComSafeArray<T>& container)
{
return CComSafeArrayIterator<T>(container, container.getSize());
}

Обратите внимание, что begin () — это нулевая позиция, end () — это позиция getSize ().

И написание итератора — это не ракетостроение. Всего несколько функций.
Самое главное, чтобы знать, что вам нужно повторить. В вашем случае: ссылка на контейнер (указатель) и текущая позиция. Итерация — это просто перемещение позиции. Доступ осуществляется через контейнер и позицию. Сравнение через сравнение позиции.

template <typename T>
class CComSafeArrayIterator {
public:
CComSafeArrayIterator(CComSafeArray<T>& container, ULONG position)
: container(&container),
position(position)
{}

// prefix ++it
CComSafeArrayIterator& operator ++() { ++position; return *this; }
// postfix it++
CComSafeArrayIterator operator ++(int) {
CComSafeArrayIterator prev = *this;
++position;
return prev;
}
// access by ->: it-> !! ony if getAt return reference not value
const T* operator -> () const {
return &(container->getAt(position));
}
// access by *: *it
const T& operator * () const {
return container->getAt(position);
}
// comparing
friend bool operator == (const CComSafeArrayIterator<T>& l,
const CComSafeArrayIterator<T>& r)
{
return l.position == r.position;
}
friend bool operator != (const CComSafeArrayIterator<T>& l,
const CComSafeArrayIterator<T>& r)
{
return l.position != r.position;
}private:
// this is what you need
CComSafeArray<T>* container;
ULONG position;
};
6

Другие решения

Других решений пока нет …