2010-07-09 17 views
6

Necesito almacenar una serie de puntos de datos en forma de (nombre, valor), donde el valor podría tomar diferentes tipos.C++ Cómo crear un contenedor heterogéneo

Estoy tratando de usar una plantilla de clase para cada punto de datos. Luego, para cada punto de datos que veo, quiero crear un nuevo objeto y volverlo a insertar en un vector. Para cada tipo nuevo, primero necesito crear una nueva clase a partir de la plantilla. Pero no puedo almacenar los objetos creados en cualquier vector, ya que los vectores esperan el mismo tipo para todas las entradas. Los tipos que necesito almacenar no se pueden ajustar en una jerarquía de herencia. No están relacionados. También puede haber más tipos creados en el futuro, y no quiero cambiar el servicio de almacenamiento para cada tipo nuevo. ¿Hay alguna manera de crear un contenedor heterogéneo para almacenar estas entradas? ¡Gracias!

+0

Muestra una forma de lidiar con el polimorfismo en tiempo de ejecución. Supongo que está relacionado. https://youtu.be/vxv74Mjt9_0?t=16m8s –

+0

Posible duplicado de [¿Cómo puedo almacenar objetos de diferentes tipos en un contenedor de C++?] (Https://stackoverflow.com/questions/4738405/how-can- i-store-objects-of-differing-types-in-ac-container) –

Respuesta

7

La biblioteca de impulso tiene probablemente lo que estás buscando (boost :: any). Puede rodar el suyo usando un enfoque de puntero envuelto si no puede usar boost ...

+1

¡Gracias! ¡Creo que "cualquiera" funcionará! También encontré un tutorial sobre esto basado en boost :: any. ¡Aquí está, si alguien necesita esto! http://www.devx.com/cplus/10MinuteSolution/29757/1954 – Abhi

0

Estaba pensando que solo podría tener un par (tipo, vacío *) y escribir su propia función pop que arroja el vacío * según sobre el tipo descrito en el par y luego empujar estos en cualquier recipiente llama la atención.

+0

como lo menciona Neil, propenso a errores e ineficiente, yo tampoco recomendaría esto. Siga la sugerencia de Neil y solo utilice la herencia o eche un vistazo a boost :: any como se mencionó anteriormente en 6502. – cjh

4

El problema con los contenedores como este es que cuando desea acceder a algo en el contenedor, debe determinar su tipo y luego convertirlo al tipo real de alguna manera. Esto es feo, ineficiente y propenso a errores, por lo que la opción n. ° 1 en C++ es usar herencia, a menos que tenga una muy buena razón para no hacerlo, algo que nunca he encontrado en mi carrera en C++.

+0

Gracias Neil! ... Así que estos tipos de datos están básicamente en todas partes, son un conjunto de perillas si te gusta . Pueden ser long int, string, bool, etc. :(Can not Use inheritance ... – Abhi

+1

El problema con los vectores y las clases de C++ es que no se puede declarar un vector de Base y luego poner instancias de Derived adentro. Debido a copiar la filosofía de C++ cualquier implementación de este tipo para std :: vector (o cualquier otro std :: contenedor) debe usar punteros (eventualmente envueltos). – 6502

+1

@Abhi En realidad se puede usar la herencia, así es como boost :: any funciona, se borra el tipo en una base privada que tiene un tipo derivado de plantilla que contiene los valores, todo esto está oculto dentro de boost :: any donde su constructor/operador de asignación hace el borrado de tipo (son plantillas). Sin embargo, sugiero que reconsidere su diseño, realmente necesito esto. –

9

boost::any ya se ha recomendado, sin embargo, es para todo, por lo que no se puede esperar mucho de él.

Si conoce los distintos tipos con anticipación, es mejor que use boost::variant.

typedef boost::variant<Foo, Bar, Joe> variant_type; 

struct Print: boost::static_visitor<> 
{ 
    void operator()(Foo const& f) const { f.print(std::cout); } 

    template <class T> 
    void operator()(T const& t) const { std::cout << t << '\n'; } 
}; 

void func(variant_type const& v) // not template 
{ 
    boost::apply_visitor(Print(), v); // compile-time checking 
            // that all types are handled 
} 
Cuestiones relacionadas