C ++将不同数据类型映射为值

时间:2014-01-27 15:26:46

标签: c++ map

我的问题如下:我想将两个(不再是)不同的数据类型作为值放入映射中。

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]] )

你能告诉我这是否可行?同样,它将仅限于两种不同的数据类型。谢谢!

7 个答案:

答案 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)变量。

此处的文档:http://qt-project.org/doc/qt-5.0/qtcore/qvariant.html

答案 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派生如下,将您的typeYBase数据类型转换为子类:

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();

注意:

  • 如果使用动态创建的typeXtypeY实例,则应优先将smart pointers存储在地图中,例如std::unique_ptr或{{ 3}},以简化内存管理。

  • 如果必须坚持使用全局func()函数,则可以从相应的成员函数中调用它们。我只是将参数转换为指针或引用,以避免复制对象。

std::shared_ptr