2011-02-27 28 views
6

Saludos.Un contenedor estándar dentro de un método de plantilla

No sé muy bien cómo explicar a mí mismo, pero creo que una pieza de código le hará entender lo que estoy intenting hacer:

template<class A, class B> 
void myFunction(A<B>& list) 
{ 
    typename A<B>::iterator current = list.begin(); 
    typename A<B>::iterator end = list.end(); 

    while (current != end) 
    { 
    current++; 
    } 
} 

Donde A es un contenedor STL (vector , lista ...). Es como un inicio, pero con plantillas: una plantilla, dentro de una plantilla, etc. ...

La cosa es: ¿qué haces cuando uno de los parámetros de tu plantilla es una plantilla ... y todavía quieres admitir todos los tipos compatibles con esta plantilla.

Esto, por supuesto, no se compila (dice 'A no es una plantilla').

¿Alguien sabe cómo crear una plantilla así?

Respuesta

2

A y B serán tipos concretos (y no plantillas), por lo tanto, A<B> no tiene sentido.

Puede escribir el código de esta manera:

template<class List> 
void myFunction(List &list) 
{ 
    typename List::iterator current = list.begin(); 
    typename List::iterator end = list.end(); 

    while (current != end) 
    { 
    current++; 
    } 
} 

Si lo que necesita saber cuál es el tipo de un elemento de esa lista, hay un typedef dentro de la lista para que:

typename List::value_type 
+1

+1, porque es la solución más simple al problema. los parámetros de la plantilla de plantilla son rápidamente desordenados, ya que requieren concordancia arity. –

7

Usted busca un parámetro de plantilla plantilla

template<template<class T, class All = std::allocator<T> > class A, class B> 
void myFunction(A<B>& list) 
{ 
    typename A<B>::iterator current = list.begin(); 
    typename A<B>::iterator end = list.end(); 

    while (current != end) 
    { 
    current++; 
    } 
} 

Sin embargo, en su caso particular, me XX tinta que estaría mejor con sólo pasar el contenedor intantiated, es decir,

template<class C> 
void myFunction(C& list) 
{ 
    ... 
} 

uso como esto

vector<char> v; 
myFunction(v); 

Su código original tendría que ser llamado como esto:

myFunction<std::vector, char> (v) 

que es mucho más detallado y no tiene ningún beneficio particular

+0

No puede usar argumentos de plantilla predeterminados en un parámetro de plantilla de plantilla, además, no puede tener argumentos de plantilla predeterminados en una plantilla de función. Por lo tanto, la versión del parámetro de plantilla de plantilla debería tener varias versiones sobrecargadas para diferentes contenedores y diferentes argumentos de plantilla predeterminados, por eso no es realmente factible. –

+0

@Mikael: No he usado argumentos predeterminados en una plantilla de función. El argumento predeterminado es el parámetro de plantilla de plantilla en sí, que es perfectamente legal –

-1

Bueno, para resolver este pequeño problema de ejemplo. Es bastante simple. vector<int> es una clase, por lo tanto, no necesita declarar el A<B> en el prototipo. Usted simplemente puede hacer esto:

template<class A> 
void myFunction(A& list) 
{ 
    typedef typename A::value_type B; //do this if you need to know the type of the elements. 
    typename A::iterator current = list.begin(); 
    typename A::iterator end = list.end(); 

    while (current != end) 
    { 
    current++; 
    } 
} 

Pero si realmente necesita, también puede declarar el argumento de plantilla como una plantilla demasiado:

template< template<class> class A, class B > 
void myFunction(A<B>& list) 
{ 
    typename A<B>::iterator current = list.begin(); 
    typename A<B>::iterator end = list.end(); 

    while (current != end) 
    { 
    current++; 
    } 
} 

Pero lo anterior no es realmente la mayoría de plantillas de clase recomendada y tener un conjunto de tipos de archivos anidados (como iterador y tipo de valor en contenedores STL) para que pueda tener acceso a toda la información que necesita sobre el tipo sin tener que usar estos parámetros de plantilla de plantilla. Por lo tanto, la primera forma es generalmente la forma preferida y más normal de hacerlo (también suele ser menos problemas para hacerlo funcionar, es decir, el compilador tiende a "disgustar" los parámetros de la plantilla de la plantilla).

Además, no puede usar contenedores STL muy fácilmente con los parámetros de plantilla de plantilla porque los contenedores STL tienen todos estos argumentos de plantilla "ocultos" (por ejemplo, "asignador" y "comparar" para contenedores ordenados). Por lo tanto, tendrías que enumerar todos estos también, de lo contrario el compilador no podrá hacer la coincidencia. Y luego, no tendrá una función muy "genérica" ​​porque tendrá que asumir tanto acerca del contenedor STL que ya pasó que solo servirá uno o dos tipos de contenedores. Realmente es mejor usar la primera manera.

+1

No se puede pasar un contenedor stl a este método, porque los contenedores STL tienen al menos 2 parámetros de plantilla –

+0

@Armen, es correcto, gracias por señalarlo. –

Cuestiones relacionadas