¿Cómo puedo almacenar objetos de diferentes tipos en un contenedor de C ++?

¿Existe un contenedor C ++ que pueda usar o construir que pueda contener, por ejemplo, int y string y tipos double ? El problema al que me enfrento es que cada vez que trato de poblar, por ejemplo, un mapa, vector o lista con, digamos, lo siguiente:

 int x; string y; double z; 

Estoy restringido con el formato:

 list mycountainer; vector mycontainer; 

lo que obliga a mycontainer a constar solo de un tipo.

Antes de que alguien sugiera generics, tampoco funcionaría, ya que el vector estándar y los contenedores de list que vienen con C ++ ya son generics : pueden ser contenedores para cualquier tipo pero no pueden contener varios tipos.

Me gustaría evitar el uso de Boost también, si es posible, preferiría que hubiera una forma sencilla de codificarlo yo.

[edit] Hola, muchas gracias por tus sugerencias. Debo explicar cómo usaré este contenedor, pero es un poco complicado, por lo tanto, la (gran) simplificación anterior. Creo que la mejor opción desde aquí es usar el Boost. Gracias de nuevo.

Puede usar (o volver a implementar) boost::any y almacenar instancias de boost::any en un contenedor. Eso sería lo más seguro, ya que boost::any probablemente se haya ocupado de la mayoría de los casos límite y la complejidad implicada en la solución de este tipo de problema en el caso general.

Si desea hacer algo rápido y sucio, cree una estructura o tal vez una unión que contenga miembros de todos los tipos posibles junto con una enumeración u otro indicador de qué tipo es ‘activo’ en el objeto. Tenga especial cuidado con los sindicatos ya que tienen algunas propiedades interesantes (como invocar un comportamiento indefinido si lee al miembro de la unión equivocado, solo uno de los miembros puede estar ‘activo’ a la vez, el último en el que se escribió).

Tengo curiosidad por lo que estás haciendo, pero necesitas una construcción así.

Bueno, la primera pregunta sería: ¿Por qué crees que necesitas almacenar objetos de tipos diferentes, totalmente no relacionados en el mismo contenedor? Eso me parece sospechoso.

Si tuviera la necesidad, buscaría boost::variant o boost::any .

Lo que quiere se llama un “contenedor hetrogenious”. C ++ técnicamente no los admite en el STL, pero Boost sí lo hace.

Teniendo en cuenta eso, creo que encontrarás tu respuesta en esta pregunta: how-do-you-make-a-heterogeneous-boostmap

Puede usar estructuras o clases o std :: pair.

[editar]

Para clases y estructuras:

 struct XYZ { int x; string y; double z; }; std::vector container; XYZ el; el.x = 10; el.y = "asd"; el.z = 1.123; container.push_back(el); 

Para std :: pair:

 #include  typedef std::pair > XYZ; std::vector container; container.push_back(std::make_pair(10, std::make_pair("asd", 1111.222))); 

Podría usar una estructura que contenga los tres.

 struct Data { int intVal; std::string stringVal; double doubleVal; }; 

Entonces podría declarar list mycontainer y usar el valor apropiado, siempre que sepa cuál es el tipo de valor. De lo contrario, agregue un campo adicional a la estructura que le indique cuál de los tres tipos de datos está en uso.

 struct Data { enum DATATYPE { DT_INT, DT_STRING, DT_DOUBLE } type; int intVal; std::string stringVal; double doubleVal; }; 

Si te preocupa el uso de la memoria, probablemente puedas utilizar una unión, aunque tiendo a evitar su uso. Sin embargo, podría ser una paranoia innecesaria de mi parte.

Si tiene un número finito de artículos que necesita almacenar, colóquelos en una clase o estructura.

Si no hay límite para los artículos que necesitaría almacenar en este contenedor, mire una forma diferente de hacer las cosas porque la única forma de hacerlo es almacenándolos como un objeto y luego colocándolos en su propio tipo cuando necesito acceder a ellos

Sin embargo, si algún elemento podría estar en el contenedor, entonces no tiene forma de saber qué tipo de elementos específicos hay en el contenedor y, por lo tanto, no podrá lanzarlos.

Si C ++ contenía la reflexión, posiblemente habría una manera de hacer esto, pero C ++ no tiene reflection.

El método más simple es, por supuesto, definir una estructura o clase que tenga miembros de cada uno de los tipos que desea almacenar. La respuesta de Josh sugiere Boost . Cualquiera , que contenga casi cualquier cosa . Si desea restringir los valores solo a los de int , double y std::string , la mejor opción sería Boost.Variant .

Si simplemente no quiere usar Boost, entonces le sugiero que supere sus complejos y lo use de todos modos. “No inventado aquí” es una política autodestructiva. Pero si no puede usar Boost, puede escribir su propia clase de variante. Andrei Alexandrescu escribió una serie de tres partes sobre eso ( parte 1 , parte 2 , parte 3 ) hace unos años, y su diseño inspiró el que utiliza Boost.