c++ templates list linker

c++ - Extendiendo std:: list



templates linker (8)

Dado el enunciado original del problema,

Necesito usar listas para mi programa y necesitaba decidir si uso std :: vector o std :: list. El problema con el vector es que no hay un método de eliminación y con la lista que no hay operador [].

no hay necesidad de crear su propia clase de lista (esta no es una opción de diseño sabia de todos modos, porque std::list no tiene un destructor virtual, lo que es una fuerte indicación de que no está destinado a usarse como una clase base) .

Aún puede lograr lo que quiere usando std::vector y la función std::remove . Si v es un std::vector<T> , entonces para eliminar el valor del value , simplemente puede escribir:

#include <vector> #include <algorithm> T value = ...; // whatever v.erase(std::remove(v.begin(), v.end(), value), v.end());

Necesito usar listas para mi programa y necesitaba decidir si uso std :: vector o std :: list. El problema con el vector es que no hay un método de eliminación y con la lista que no hay operador []. Así que decidí escribir mi propia clase extendiendo std :: list y sobrecargando el operador [].

Mi código se ve así:

#include <list> template <class T > class myList : public std::list<T> { public: T operator[](int index); T operator[](int & index); myList(void); ~myList(void); }; #include "myList.h" template<class T> myList<T>::myList(void): std::list<T>() {} template<class T> myList<T>::~myList(void) { std::list<T>::~list(); } template<class T> T myList<T>::operator[](int index) { int count = 0; std::list<T>::iterator itr = this->begin(); while(count != index)itr++; return *itr; } template<class T> T myList<T>::operator[](int & index) { int count = 0; std::list<T>::iterator itr = this->begin(); while(count != index)itr++; return *itr; }

Puedo compilarlo pero obtengo un error de enlazador si trato de usarlo. ¿Algunas ideas?


Dependiendo de sus necesidades, debe usar std::vector (si necesita agregar / eliminar a menudo al final, y acceso aleatorio), o std::deque (si necesita agregar / eliminar a menudo al final o al principio, y su conjunto de datos es enorme, y todavía quiere acceso aleatorio). Aquí hay una buena imagen que le muestra cómo tomar la decisión:

Opción de contenedor http://adrinael.net/containerchoice.png


Los vectores tienen el método de borrado que puede eliminar elementos. ¿No es eso suficiente?


No es necesario llamar a destructor de std :: list, porque ya deriva de std :: list cuando destructor invocó myList automáticamente se llamará a std :: list destructor.


Tienes que mover todo tu código de plantilla en el encabezado.


Todo el código de la plantilla debe colocarse en el archivo de encabezado. Esta solución de relleno vincula problemas (esa es la manera más simple). La razón por la que sucede es porque los compiladores compilan cada archivo fuente (.cc) por separado de otros archivos. Por otro lado, necesita saber qué código exactamente necesita crear (es decir, en qué se sustituye la plantilla T en) y no tiene otra forma de saberlo a menos que el programador lo diga explícitamente o incluya todo el código cuando la plantilla instanciación sucede. Es decir, cuando se compila mylist.cc, no sabe nada sobre los usuarios de mi lista y qué código debe crearse. Por otro lado, si listuser.cc está compilado y todo el código mylist está presente, el compilador crea el código mylist necesario. Puedes leer más sobre esto aquí o en Stroustrup.

Su código tiene problemas, ¿qué sucede si el usuario lo solicita como negativo o demasiado grande (más que la cantidad de elementos en la lista)? Y no miré demasiado.

Además, no sé cómo planeas usarlo, pero tu operador [] es O (N) vez, lo que probablemente conduzca fácilmente a O (N * N) bucles ...


Además de otros excelentes comentarios, la mejor forma de extender un contenedor estándar no es por derivación, sino por escribir funciones gratuitas. Por ejemplo, vea cómo se pueden usar los algoritmos Boost String para extender std::string y otras clases de cadenas.


Lo obvio ya se ha descrito en detalles:

¿Pero los métodos que eliges implementar?

  • Incinerador de basuras.
    • No es necesario que el compilador genere eso para usted.
  • Las dos versiones diferentes de operador [] no tienen sentido
    • También deberías usar uisng std :: list :: size_type como índice
    • A menos que tenga la intención de soportar índices negativos.
  • No hay versiones de const del operador []
  • Si va a implementar [] también debería hacerlo a ()
  • Te perdiste todas las diferentes formas de construir una lista.
  • Los contenedores deben definir varios tipos internamente