Pregunta

Quiero tener un mapa que tenga un tipo de clave homogéneo pero tipos de datos heterogéneos.

Quiero poder hacer algo como (pseudocódigo):

boost::map<std::string, magic_goes_here> m;
m.add<int>("a", 2);
m.add<std::string>("b", "black sheep");

int i = m.get<int>("a");
int j = m.get<int>("b"); // error!

Podría tener un puntero a una clase base como tipo de datos, pero preferiría que no.

Nunca he usado boost antes, pero he mirado la biblioteca de fusión pero no puedo entender lo que necesito hacer.

Gracias por su ayuda.

¿Fue útil?

Solución

#include <map>
#include <string>
#include <iostream>
#include <boost/any.hpp>

int main()
{
    try
    {
        std::map<std::string, boost::any> m;
        m["a"]  = 2;
        m["b"]  = static_cast<char const *>("black sheep");

        int i = boost::any_cast<int>(m["a"]);
        std::cout << "I(" << i << ")\n";

        int j = boost::any_cast<int>(m["b"]); // throws exception
        std::cout << "J(" << j << ")\n";
    }
    catch(...)
    {
        std::cout << "Exception\n";
    }

}

Otros consejos

¿Cómo puedo construir un < contenedor favorito > ; de objetos de diferentes tipos?

  

No puedes, pero puedes fingirlo bastante bien. En C / C ++, todas las matrices son homogéneas (es decir, todos los elementos son del mismo tipo). Sin embargo, con una capa adicional de indirección puede dar la apariencia de un contenedor heterogéneo (un contenedor heterogéneo es un contenedor donde los objetos contenidos son de diferentes tipos).

     

Hay dos casos con contenedores heterogéneos.

     

El primer caso ocurre cuando todos los objetos que desea almacenar en un contenedor se derivan públicamente de una clase base común. [...]

     

El segundo caso ocurre cuando los tipos de objeto son disjuntos & # 8212; no comparten una clase base común.
  El enfoque aquí es usar una clase de identificador. El contenedor es un contenedor de objetos de control (por valor o por puntero, su elección; por valor es más fácil). Cada objeto de manejador sabe cómo & "; Mantener &"; (es decir, mantenga un puntero hacia) uno de los objetos que desea colocar en el contenedor. Puede usar una clase de identificador único con varios tipos diferentes de punteros como datos de instancia, o una jerarquía de clases de identificador que sombree los diversos tipos que desea contener (requiere que el contenedor sea de punteros de clase base de identificador). La desventaja de este enfoque es que abre la (s) clase (s) de manejo al mantenimiento cada vez que cambia el conjunto de tipos que pueden estar contenidos. El beneficio es que puede usar las clases de identificador para encapsular la mayor parte de la fealdad de la administración de memoria y la vida útil de los objetos. Por lo tanto, usar objetos de control puede ser beneficioso incluso en el primer caso.

¿ boost :: any do ¿El truco para ti?

Gracias David, eso era lo que necesitaba. Aquí está la solución de trabajo.

#include <iostream>
using std::cout;
using std::endl;

#include <map>
#include <boost/any.hpp>

using boost::any_cast;
typedef std::map<std::string, boost::any> t_map;


int main(int argc, char **argv)
{

  t_map map;
  char *pc = "boo yeah!";

  map["a"] = 2.1;
  map["b"] = pc;

  cout << "map contents" << endl;
  cout << any_cast<double>(map["a"]) << endl;
  cout << any_cast<char*>(map["b"]) << endl;

  return 0;
}

Si desea que se admita un conjunto limitado de tipos, Boost.Variant debería hacer el truco.

boost any seguramente funciona, pero creo que usar Int para escribir Tecnología como el tipo clave de mapa de fusión es una mejor solución. Sin tipo de borrado y posiblemente más rápido

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top