2010-05-18 9 views
5

Ich habe einen beliebigen STL-Container C, der Elemente eines beliebigen Typs T enthält. Ich möchte einen std :: vector erstellen, der eine Kopie aller Elemente enthält. Was ist der sauberste Weg, dies zu tun?Funktionsvorlagen für beliebige STL-Container mit beliebigen Typen

template <typename C> 
void myfunction(C container){ 

    /*Derive the type T of elements within the container*/ 

    std::vector<T> mystack; 

    /* Iterate over container and push_back() the elements into mystack*/ 
} 

Antwort

11

STL Strukturen wie vector und set sollte die value_type Typ enthalten, die typedef-ED T ist.

std::vector<typename C::value_type> mystack; 

BTW, Sie müssen nicht selbst über den Container iterieren. Verwenden Sie einfach

+0

Ich dachte, ich würde dies für C++ 11 stoßen. Würde das neue Keyword "auto" hier funktionieren? Ich hatte noch keine Gelegenheit, damit viel zu spielen. –

+0

@ChadBrewbaker: Nein. 'Declltype' würde funktionieren, aber das ist nicht einfacher als' typename C :: value_type'. – kennytm

10

Für Container hat Kenny die richtige Lösung gegeben. Viele Funktionen in C++ verwenden jedoch Paare von Iteratoren anstelle von Containern ... hier kann die gleiche Logik angewendet werden. Iteratoren iterator_traits Informationen über ihre verwandten Arten zu schaffen, verwenden:

template <typename It> 
void myfunction(It start, It end) { 
    // Get value for iterator: 

    typedef typename std::iterator_traits<It>::value_type T; 

    // Do something, e.g. calculate the minimum: 

    T min_value = *std::min_element(start, end); 
} 

By the way, ist typename notwendig in dem typedef weil value_type ist ein so genannter abhängig Typ, dh es ist von der Art eines Template-Argument hängt und der C++ - Compiler kann in diesem Zusammenhang nicht selbst herausfinden, dass er auf einen Typnamen (und nicht etwa eine statische Methode oder Variable) verweist.

+3

Das ist eine nette Ergänzung zu Kennys Antwort, obwohl ich mich viel besser fühlen würde, wenn Sie keinen Iterator nennen würden, der _one das letzte gültige Element_ übergibt, das gleiche wie eine gewöhnliche Container-Member-Funktion, die das letzte gültige Element abruft. Das ist viel zu viel Verwirrungspotenzial. – sbi

+0

@sbi: ** D'oh! ** Ich habe diese Schreibweise seit Jahren einheitlich in meinem eigenen Code * verwendet und habe nie gemerkt, dass es bei der Verwendung von STL so stark zu Konflikten kommt. Schlecht schlecht schlecht schlecht. :-( –

+0

Ich benutze 'first',' last', wie STL-Algorithmen. Du musst damit umgehen, dass "last" der letzte Iterator * von * der Bereich ist, nicht der Iterator, der auf das letzte Element zeigt * in * dem Bereich –