2010-05-18 14 views
5

Tengo un contenedor STL arbitrario C, que contiene elementos de un tipo arbitrario T. Quiero crear un std :: vector que tenga una copia de todos los elementos. ¿Cuál es la forma más limpia de hacer esto?Plantillas de función para contenedores STL arbitrarios que contienen tipos arbitrarios

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*/ 
} 

Respuesta

11

estructuras STL como vector y set deben contener el tipo value_type que es typedef-ed a T.

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

Por cierto, no necesita repetir el contenedor usted mismo. Solo use

template <typename C> 
void myfunction(const C& container){ 
    std::vector<typename C::value_type> mystack(container.begin(), container.end()); 
    ... 
} 
+0

Pensé que podría topar con esto para C++ 11. ¿La nueva palabra clave "auto" funcionaría aquí? No he tenido la oportunidad de jugar con eso mucho. –

+0

@ChadBrewbaker: No. 'decltype' funcionaría, pero eso no es más simple que' typename C :: value_type'. – kennytm

10

Para contenedores, Kenny ha dado la solución correcta. Sin embargo, muchas funciones en C++ toman pares de iteradores en lugar de contenedores ... la misma lógica se puede aplicar aquí. Iteradores utilizan iterator_traits para proporcionar información sobre sus tipos relacionados:

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

Por cierto, typename es necesario en el typedef porque value_type es un llamado dependientes tipo, es decir, que depende de la naturaleza de un parámetro de plantilla y el compilador de C++ no puede entender por sí solo que se refiere a un nombre de tipo (en lugar de, digamos, un método o variable estático) en este contexto.

+3

Es una buena adición a la respuesta de Kenny, aunque me sentiría mucho mejor si no nombrara un iterador apuntando _un pasado el último elemento válido_ lo mismo que una función de miembro de contenedor común recuperando el último elemento válido. Eso es mucho potencial de confusión. – sbi

+0

@sbi: ** D'oh! ** He usado esta notación en mi propio código de forma consistente * durante años * y nunca me di cuenta de que entra en conflicto con el uso de STL. Malo, malo, malo, malo :-( –

+0

Utilizo 'first',' last', como lo hacen los algoritmos STL. Tiene que lidiar con el hecho de que "last" es el último iterador * de * el rango, no el iterador que apunta al último elemento * en * el rango. –

Cuestiones relacionadas