【问题标题】:how do you make a heterogeneous boost::map?你如何制作一个异构的 boost::map?
【发布时间】:2010-09-20 01:36:03
【问题描述】:

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

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

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

感谢您的帮助。

【问题讨论】:

  • 如果你知道所有可能的类型,你可能想在地图中填充,那么boost::variant 会很好用。如果你想要任何类型,那么boost::any 是要走的路。

标签: c++ boost map


【解决方案1】:
#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";
    }

}

【讨论】:

  • 你可以使用std::decay来代替cumbersome_cast。
  • 不只是使用 std::map 而不是 boost map 初始化为here 吗?
【解决方案2】:

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

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

异构容器有两种情况。

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

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

【讨论】:

    【解决方案3】:

    boost::any 会为您解决问题吗?

    【讨论】:

      【解决方案4】:

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

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

      【讨论】:

      • 这应该是const char *pc = "boo yeah!";
      【解决方案5】:

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

      【讨论】:

        【解决方案6】:

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

        【讨论】:

          猜你喜欢
          • 2011-10-02
          • 2021-09-19
          • 1970-01-01
          • 1970-01-01
          • 2013-05-27
          • 2020-08-07
          • 2014-08-22
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多