32

我想要一个具有同构键类型但异构数据类型的映射。

我希望能够做类似(伪代码)的事情:

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,但看过 fusion 库,但不知道我需要做什么。

谢谢你的帮助。

4

6 回答 6

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

}
于 2008-10-30T23:12:08.610 回答
10

如何构建不同类型对象的 <favorite container>?

你不能,但你可以很好地伪造它。在 C/C++ 中,所有数组都是同构的(即元素都是相同的类型)。但是,通过额外的间接层,您可以呈现出异构容器的外观(异构容器是其中包含的对象具有不同类型的容器)。

异构容器有两种情况。

第一种情况发生在您要存储在容器中的所有对象都是从公共基类公开派生的情况下。[...]

第二种情况发生在对象类型不相交时——它们不共享一个公共基类。
这里的方法是使用句柄类。容器是句柄对象的容器(按值或按指针,您可以选择;按值更容易)。每个句柄对象都知道如何“保持”(即维护指向)您要放入容器中的对象之一。您可以使用具有几种不同类型指针的单个句柄类作为实例数据,也可以使用隐藏您希望包含的各种类型的句柄类层次结构(要求容器是句柄基类指针)。这种方法的缺点是,每次更改可以包含的类型集时,它都会打开句柄类进行维护。好处是您可以使用句柄类来封装内存管理和对象生命周期的大部分丑陋。

于 2008-10-30T19:28:40.247 回答
8

boost::any对你有用吗?

于 2008-10-30T19:28:48.607 回答
7

谢谢大卫,这正是我所需要的。这是有效的解决方案。

#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;
}
于 2008-10-31T00:04:10.533 回答
5

如果您希望支持一组有限的类型,Boost.Variant应该可以解决问题。

于 2008-10-30T20:22:43.553 回答
0

boost any 肯定有效,但我认为使用 Int 键入 Technology 作为融合映射的关键类型是更好的解决方案。没有类型擦除,可能更快

于 2017-05-14T14:00:23.860 回答