Domanda

Voglio avere una mappa che abbia un tipo di chiave omogenea ma tipi di dati eterogenei.

Voglio essere in grado di fare qualcosa del tipo (pseudo-codice):

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!

Potrei avere un puntatore a una classe base come tipo di dati, ma preferirei non farlo.

Non ho mai usato boost prima ma ho guardato alla libreria di fusione ma non riesco a capire cosa devo fare.

Grazie per il tuo aiuto.

È stato utile?

Soluzione

#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";
    }

}

Altri suggerimenti

Come posso creare un < contenitore preferito > ; di oggetti di diverso tipo?

  

Non puoi, ma puoi fingere abbastanza bene. In C / C ++ tutti gli array sono omogenei (vale a dire, gli elementi sono tutti dello stesso tipo). Tuttavia, con un ulteriore livello di riferimento indiretto è possibile dare l'aspetto di un contenitore eterogeneo (un contenitore eterogeneo è un contenitore in cui gli oggetti contenuti sono di diversi tipi).

     

Esistono due casi con contenitori eterogenei.

     

Il primo caso si verifica quando tutti gli oggetti che si desidera archiviare in un contenitore derivano pubblicamente da una classe base comune. [...]

     

Il secondo caso si verifica quando i tipi di oggetto sono disgiunti & # 8212; non condividono una classe base comune.
  L'approccio qui è di usare una classe handle. Il contenitore è un contenitore di oggetti handle (per valore o per puntatore, la tua scelta; per valore è più facile). Ogni oggetto handle sa come & Quot; tenere premuto & Quot; (ad esempio, mantenere un puntatore a) uno degli oggetti che si desidera inserire nel contenitore. È possibile utilizzare una singola classe handle con diversi tipi di puntatori come dati di istanza o una gerarchia di classi handle che ombreggiano i vari tipi che si desidera contenere (richiede che il contenitore sia di puntatori della classe base handle). Il rovescio della medaglia di questo approccio è che apre le classi di handle alla manutenzione ogni volta che modifichi l'insieme di tipi che possono essere contenuti. Il vantaggio è che è possibile utilizzare le classi di handle per incapsulare la maggior parte della bruttezza della gestione della memoria e della durata degli oggetti. Pertanto, l'utilizzo degli oggetti handle può essere utile anche nel primo caso.

Grazie David, era quello di cui avevo bisogno. Ecco la soluzione funzionante.

#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;
}

Se desideri supportare un set limitato di tipi, Boost.Variant dovrebbe fare il trucco.

incrementa sicuramente qualsiasi lavoro, ma penso che usare Int per digitare la tecnologia come tipo chiave di mappa di fusione sia una soluzione migliore. Nessuna cancellazione del tipo e forse più veloce

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top