2012-10-16 15 views
5

ho alcune funzioni che utilizzo per convertire una variante SAFEARRAY 2D in vari contenitori STL, un pò come così (illustrativi)funzione generica per convertire variante SAFEARRAY di contenitori 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; 
} 

ritengo che non è molto C++ - ish modo di andare su di esso e significa che c'è una funzione separata per ogni contenitore STL in cui mi converto.

La mia idea era quella di scrivere un iteratore involucro e personalizzato per CComSafeArrays quindi ho potuto solo fare ...

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

ma avendo mai scritto un iteratore prima e di essere un novizio Io davvero non so se sarà facile.

È un iteratore CComSafeArray personalizzato, la mia migliore opzione standard C++ come (nel qual caso sono sicuro di poter trovare un buon tutorial sulla scrittura di un iteratore)? O c'è un altro modo di affrontarlo?

Boost non è un'opzione.

TIA

risposta

6

La mia idea era quella di scrivere un iteratore involucro e personalizzato per CComSafeArrays

Questo è molto buona idea per la creazione di iteratore, ma non hai bisogno di un wrapper CComSafeArray<T>, solo è necessario l'iteratore.

così ho potuto solo fare ...

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

Ma invece di fare la tua strada, si può fare questo:

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

Perché contenitore quasi ogni STL ha costruttore da range (coppia di iteratori).

Supponendo che hai scritto iteratore su CComSafeArray<T> - funzioni iniziano/finale sarà come questi:

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

noti che iniziano() è la posizione di zero, end() è getSize posizione().

E scrivere un iteratore non è scienza missilistica. Solo alcune funzioni Il più importante è sapere cosa è necessario per iterare. Nel tuo caso: il riferimento del contenitore (puntatore) e la posizione corrente. L'iterazione sta semplicemente spostando la posizione. L'accesso avviene tramite container e posizione. Il confronto è tramite il confronto della posizione.

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

l'iteratore non è copiabile, ma è risolvibile passando da 'contenitore' da un riferimento a un puntatore. –

+0

@MooingDuck buona cattura, risolverà – PiotrNycz

+0

Ha funzionato come un fascino, grazie :-) – Sparkles