uso de plantillas con varios tipos de objetos

Necesito escribir una clase de plantilla de contenedor <T, R> donde T es un objeto y R puede ser vector<T*> or list<T*>. Necesito admitir operaciones comunes como insertar (T) tamaño (), etc.

Estoy sosteniendo a un miembro de la clase llamado T data ser la lista o el vector. el problema es, ¿cómo escribo el código para que en tiempo de ejecución sepa qué operación invocar desde std::list or std::vector ?

por ejemplo, para obtener el primer elemento en el contenedor, tendría que invocar data[0] en el caso del vector y data.front() en caso de listas. ¿Debería usar typeid operador?

if (typeid(R) ==  typeid(vector<T*>))
  then ...
else if (typeid(R) == typeid(list<T*>))
 then ...

O hay un mejor camino ?

preguntado el 22 de mayo de 12 a las 13:05

Cada vez que escribes if árbol con typeid en ella, lo estás haciendo mal. En este caso, tanto la lista como el vector comparten gran parte de la interfaz, incluyendo front(). -

4 Respuestas

Debe utilizar la especialización de plantilla. Puedes leer un buen artículo al respecto. aquí.

contestado el 22 de mayo de 12 a las 13:05

Puede usar iteradores: son modismos estándar en STL. Usar begin() para que el iterador apunte al comienzo de la colección y end() para obtener el final (más precisamente, el iterador que apunta al elemento "después" del último en la colección). También puedes usar push_back() con ambos list<> y vector<> para añadir elementos al final de la colección, insert() para añadir un elemento a una posición específica y erase para eliminar un elemento de la colección. Mira la referencia (vector, --) para funciones más comunes.

La idea es que las llamadas a métodos en las plantillas no se verifiquen hasta el punto de creación de instancias (y específicamente hasta la llamada de las funciones de la plantilla), por lo que las llamadas mencionadas anteriormente se vincularán al tipo de colección exacto que especificó en la plantilla.

contestado el 22 de mayo de 12 a las 13:05

Eso no impedirá el uso de algún otro contenedor que también admita iteradores y push_back(). - Simon Toth

No es tanto que quiera evitar otros contenedores tanto como quiero duplicar el código lo menos posible. Todavía no estoy seguro de cuál sería el mejor enfoque de lo mencionado aquí y lo que escribió @mfontanini: Michael

@Michael: creo que Let_Me_Be significaba que también puede usar este enfoque con otras colecciones (no solo vector y lista), lo cual es algo bueno. No enfaticé esto en mi respuesta, ya que estaba buscando específicamente un vector y una lista: Attila

@Michael: mi sugerencia funcionará "lista para usar" con la mayoría de los contenedores STL (que admiten las operaciones que desea usar), mientras que necesitará escribir más código para la especialización de cada caso si sigue el enfoque de mfontanini: Attila

Si el conjunto es tan limitado, puede hacer algo como esto:

#include <vector>
#include <list>
using namespace std;

template < typename T, typename V >
class X;

class XImpl {};

template < typename T >
class X< T, vector<T*> > : XImpl {};


template < typename T >
class X< T, list<T*> > : XImpl {};

int main()
{
    X< int,vector<int*> > a;
    X< double, list<double*> > b;
    X<int, int> c; // error
}

Y ponga su implementación en XImpl.

Editar: lo más probable es que XImpl también tenga una plantilla. Este código solo demuestra la protección contra cualquier otro contenedor que no sea un vector o una lista. Y, por supuesto, una protección contra malas combinaciones como X<int, vector<double*> >.

contestado el 22 de mayo de 12 a las 13:05

La respuesta es la que dio mfontanini, especialización de uso. Sin embargo, para su ejemplo específico, el vector también admite el frente, y el vector y la lista tienen las mismas funciones tanto como sea posible

contestado el 22 de mayo de 12 a las 13:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.