C++ 你如何制作异构 boost::map?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/251403/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 14:03:35  来源:igfitidea点击:

how do you make a heterogeneous boost::map?

c++boostmap

提问by Kurt

I want to have a map that has a homogeneous key type but heterogeneous data types.

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

I want to be able to do something like (pseudo-code):

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

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!

I could have a pointer to a base class as the data type but would rather not.

我可以有一个指向基类的指针作为数据类型,但宁愿不这样做。

I've never used boost before but have looked at the fusion library but can't figure out what I need to do.

我以前从未使用过 boost,但看过融合库,但不知道我需要做什么。

Thanks for your help.

谢谢你的帮助。

回答by Martin York

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

}

回答by Leon Timmermans

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

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

You can't, but you can fake it pretty well. In C/C++ all arrays are homogeneous (i.e., the elements are all the same type). However, with an extra layer of indirection you can give the appearance of a heterogeneous container (a heterogeneous container is a container where the contained objects are of different types).

There are two cases with heterogeneous containers.

The first case occurs when all objects you want to store in a container are publicly derived from a common base class. [...]

The second case occurs when the object types are disjoint — they do not share a common base class.
The approach here is to use a handle class. The container is a container of handle objects (by value or by pointer, your choice; by value is easier). Each handle object knows how to "hold on to" (i.e., maintain a pointer to) one of the objects you want to put in the container. You can use either a single handle class with several different types of pointers as instance data, or a hierarchy of handle classes that shadow the various types you wish to contain (requires the container be of handle base class pointers). The downside of this approach is that it opens up the handle class(es) to maintenance every time you change the set of types that can be contained. The benefit is that you can use the handle class(es) to encapsulate most of the ugliness of memory management and object lifetime. Thus using handle objects may be beneficial even in the first case.

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

异构容器有两种情况。

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

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

回答by activout.se

Would boost::anydo the trick for you?

提振::任何为你做的把戏?

回答by Kurt

Thank you David, that was what I needed. Here's the working solution.

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

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

回答by Ferruccio

If you want a limited set of types to be supported, Boost.Variantshould do the trick.

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

回答by FaceBro

boost any surely works, but I think using Int to type Technology as the key type of fusion map is a better solution. No type erasure and possibly faster

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