我希望有一个具有同类密钥类型但是异构数据类型的映射。
我希望能够做类似(伪代码)的事情:
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!
我可以将指向基类的指针作为数据类型,但不愿意。
我之前从未使用过boost,但是看过融合库但却无法弄清楚我需要做什么。
感谢您的帮助。
答案 0 :(得分:38)
#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 :(得分:10)
How can I build a <favorite container> of objects of different types?
你不能,但你可以很好地伪造它。在C / C ++中,所有数组都是同类的(即,元素都是相同的类型)。但是,通过额外的间接层,您可以提供异构容器的外观(异构容器是包含的对象具有不同类型的容器)。
异构容器有两种情况。
当您要存储在容器中的所有对象都是从公共基类公开派生时,会出现第一种情况。 [...]
第二种情况发生在对象类型不相交时 - 它们不共享公共基类 这里的方法是使用句柄类。容器是句柄对象的容器(通过值或指针,您的选择;通过值更容易)。每个句柄对象都知道如何“保持”(即,保持指针)您想要放入容器中的一个对象。您可以使用具有多种不同类型指针的单个句柄类作为实例数据,也可以使用处理类的层次结构来隐藏您希望包含的各种类型(要求容器具有句柄基类指针)。这种方法的缺点是每次更改可以包含的类型集时,它都会打开句柄类进行维护。好处是你可以使用句柄类来封装大部分内存管理和对象生命周期的丑陋。因此,即使在第一种情况下,使用手柄对象也可能是有益的。
答案 2 :(得分:8)
boost::any会为你做点什么吗?
答案 3 :(得分:6)
谢谢大卫,这就是我所需要的。这是工作解决方案。
#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;
}
答案 4 :(得分:5)
如果您希望支持一组有限的类型,Boost.Variant应该可以解决问题。
答案 5 :(得分:0)
提升任何肯定有效,但我认为使用Int键入技术作为融合地图的关键类型是一个更好的解决方案。没有类型擦除,可能更快