2012-10-16 14 views
5

mam pewne funkcje, które używam do konwersji 2D wariantowej SAFEARRAY do różnych pojemników STL, trochę jak tak (tylko ilustracyjne)Generic funkcja konwersji wariantowej SAFEARRAY do kontenerów 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; 
} 

czuję, że nie jest to bardzo C++ - ish sposób na poruszanie się o tym i oznacza to, że istnieje oddzielna funkcja dla każdego kontenera STL, który konwertuję.

Mój pomysł był napisać otoki i niestandardowe iterator dla CComSafeArrays więc mogę po prostu zrobić ...

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

ale że nigdy napisany iterator przed i będąc początkującym ja naprawdę nie wiem, czy to będzie łatwe.

Czy niestandardowy iterator CComSafeArray jest moją najlepszą, standardową opcją C++ like (w takim przypadku jestem pewien, że mogę znaleźć dobry samouczek na temat pisania iteratora)? Czy jest jakiś inny sposób, aby to osiągnąć?

Zwiększenie nie jest opcją.

TIA

Odpowiedz

6

Mój pomysł był napisać otoki i niestandardowe iterator dla CComSafeArrays

Jest to bardzo dobry pomysł na stworzenie iterator, ale nie trzeba owijkę wokół CComSafeArray<T> tylko iterator jest potrzebny.

więc może po prostu zrobić ...

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

Ale zamiast robić na swój sposób, można to zrobić:

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

Ponieważ prawie każdy pojemnik ma konstruktora z STL zakres (para iteratorów).

Zakładając masz napisane iterator nad CComSafeArray<T> - funkcje rozpocząć/końcowy będzie takie jak:

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()); 
} 

Zauważ, że begin() jest zerowa pozycja, end() jest getSize (pozycja).

Pisanie iteratora nie jest nauką rakietową. Tylko kilka funkcji. Najważniejsze to wiedzieć, co jest potrzebne do iteracji. W twoim przypadku: odniesienie do kontenera (wskaźnik) i aktualna pozycja. Iterowanie to po prostu przesuwanie pozycji. Dostęp jest przez pojemnik i pozycję. Porównanie polega na porównywaniu pozycji.

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; 
}; 
+1

Twój iterator nie jest kopiowalny, ale można go naprawić, przełączając 'container' z odwołania do wskaźnika. –

+0

@MooingDuck dobry połów, naprawiony – PiotrNycz

+0

Pracował jak urok, dzięki :-) – Sparkles

Powiązane problemy