2008-10-30 13 views
28

Homojen bir anahtar türü ancak heterojen veri türleri olan bir haritaya sahip olmak istiyorum.nasıl heterojen bir destek oluşturursunuz :: map?

I (sözde kod) gibi bir şey yapabilmek istiyorum:

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! 

Veri türü olarak bir temel sınıf için bir işaretçi var ama would rather olamazdı.

Daha önce hiç güç kullanmadım ama füzyon kütüphanesine baktım ama ne yapmam gerektiğini anlayamıyorum. Yardımlarınız için

teşekkürler.

+2

'boost :: variant' –

+0

Haritaya yerleştirmek isteyebileceğiniz tüm olası türleri biliyorsanız," boost :: variant "harika çalışır. Eğer kelimenin tam anlamıyla herhangi bir türünü istiyorsanız, o zaman “boost :: any” gitmek için bir yoldur. – Kurt

cevap

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

} 
+1

cumbersome_cast yerine 'std :: decay' kullanabilirsiniz. –

+0

sadece std :: map betiğini başlangıçta olduğu gibi yükseltmek yerine [burada] (http://www.boost.org/doc/libs/1_35_0/libs/fusion/doc/html/fusion/container/map. html)? – Tab

9

How can I build a <favorite container> of objects of different types?

Yapamazsın, ancak sahte oldukça iyi olabilir. C/C++ 'da tüm diziler homojendir (yani, elemanlar hepsi aynı tiptedir). Bununla birlikte, ekstra bir dolaylı katman ile heterojen bir konteynerin görünüşünü verebilirsiniz (heterojen bir kap, içerilen nesnelerin farklı tiplerde olduğu bir konteynırdır).

Heterojen kaplar ile iki durum vardır.

İlk durumda, kapsayıcıda depolamak istediğiniz tüm nesneler genel olarak ortak bir temel sınıftan türetildiğinde oluşur. [...]

İkinci durum, nesne türleri ayrıldığında ortaya çıkar; ortak bir temel sınıf paylaşmazlar.
Buradaki yaklaşım, bir tutamak sınıfı kullanmaktır. Kap, bir tutamaç nesnesi konteynırdır (değere veya işaretçiye göre, seçiminize göre; değer daha kolaydır). Her tutamaç nesnesi, konteynere koymak istediğiniz nesnelerden birinin nasıl tutulacağını (yani, bir işaretçiyi nasıl tutacağını) bilir. Örnek verisi olarak birkaç farklı tipte işaretçi içeren tek bir tanıtıcı sınıfı veya içermek istediğiniz çeşitli türleri gölgelendiren bir tutamaç sınıfları hiyerarşisi kullanabilirsiniz (kapsayıcıyı temel sınıf tanıtıcılarından biri gerektirir). Bu yaklaşımın dezavantajı, içerilen tiplerin setini her değiştirdiğinizde, idare edilen kol sınıfını (s) bakımını açmasıdır. Bunun avantajı, bellek yönetiminin ve nesne kullanım ömrünün çirkinliğinin çoğunu kapsüllemek için sap sınıfını (ları) kullanabilmenizdir. Bu nedenle, kulp nesnelerinin kullanılması ilk durumda bile faydalı olabilir.

5

Sınırlı sayıda türün desteklenmesini istiyorsanız, Boost.Variant numaranızı yapmalısınız.

5

Teşekkür ederim David, ihtiyacım olan buydu. İşte çalışma çözümü.

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

bu, const char * pc = "boo evet!"; –

0

boost herhangi mutlaka çalışır, ancak ben füzyon haritanın anahtar türü daha iyi bir çözüm olduğu gibi Teknoloji yazmak için Int kullanarak düşünüyorum. Hiçbir tür silme ve muhtemelen daha hızlı