我的问题如下:我想将两个(不再是)不同的数据类型作为值放入映射中。
typeX A, B, ...;
typeY Z, Y, ...;
void func (typeX) { ... }
void func (typeY) { ... }
std::map <std::string, what_to_put_here?? >map;
map["a"] = A;
map["z"] = Z;
...
std::vector<std::string> list;
//this list will be sth. like "a", "y", ...
for (unsigned int i = 0; i < list.size(); ++i)
func( map[list[i]] )
显然这不起作用,因为地图只接受一种数据类型的值。当循环“list”时,对“func”的调用应该是明确的,因为map [list [i]]的类型是已知的。
我想避免显式强制转换或类型检查,例如......
if (typeid( map[list[i]] ).name() == "typeX")
func( map[list[i]] )
else if (typeid( map[list[i]] ).name() == "typeY")
func( map[list[i]] )
你能告诉我这是否可行?同样,它将仅限于两种不同的数据类型。谢谢!
答案 0 :(得分:3)
您想使用boost::variant
:
std::map <std::string, boost::variant<typeX, typeY>>
答案 1 :(得分:2)
typeBase类的typeX和typeY子类?
如果是这样,您可以std::map<std::string,typeBase*>
在地图中存储typeX *和typeY *。
答案 2 :(得分:1)
通过一些元编程,您可以轻松地构建异构映射,该映射可以存储来自给定类型集的任何类型。 Here is an example这样做,没有类型擦除,也不需要访问值。
答案 3 :(得分:1)
实现多类型映射的一种方法是使用C ++ 11中std :: tuple的漂亮功能,它允许通过类型键进行访问。您可以将其包装以通过任意键创建访问权限。这里有一个深入的解释(以及非常有趣的读物):
https://jguegant.github.io/blogs/tech/thread-safe-multi-type-map.html
答案 4 :(得分:0)
这可能是极端矫枉过正,但QT有一个名为QVariant的变量,可用于映射到不同类型的(QT)变量。
答案 5 :(得分:0)
您需要type erasure。
Type erasure是隐藏基础类型的模式,这些已知示例是boost::any,但请记住,boost any具有动态多态行为(运行时动态调度)。另一方面,boost :: variant是另一个例子,它使用模板元编程技术。见variant vs any
最简单的解决方案是,可以使用枚举类型编写自己的类类型擦除。
答案 6 :(得分:0)
如果您不想使用Boost,那么我认为以proposed by rom1504构建类层次结构是有意义的。我将使用func()
作为成员函数来实现abstract base class,如下所示:
class Base {
public:
virtual void func() = 0;
};
void Base::func() {};
然后,通过从typeX
派生如下,将您的typeY
和Base
数据类型转换为子类:
class typeX : public Base {
public:
void func() { std::cout << "typeX::func()" << std::endl; };
int i; // Example for your original 'typeX' content.
};
class typeY : public Base {
public:
void func() { std::cout << "typeY::func()" << std::endl; };
std::string s; // Example for your original 'typeY' content.
};
这里,func()
实现将采用您相应的全局func()
函数的内容。接下来,您的地图需要将指向Base
的指针存储为值:
std::map<std::string, Base*> map;
map["a"] = &A;
map["z"] = &Z;
因此,您可以按以下方式实现循环(使用C++11 range-based for
loop):
for (auto const &list_item : list)
map[list_item]->func();
注意:
如果使用动态创建的typeX
和typeY
实例,则应优先将smart pointers存储在地图中,例如std::unique_ptr
或{{ 3}},以简化内存管理。
如果必须坚持使用全局func()
函数,则可以从相应的成员函数中调用它们。我只是将参数转换为指针或引用,以避免复制对象。