如何使用具有不同类型值的映射

How to have a map with different types of values?

本文关键字:映射 同类型 何使用      更新时间:2023-10-16

我需要一个以int为键和值的映射,它可以是各种类型的对象

std::map<int, differenttypes*> mapping;

并提取像这样的对象

 dialog* newDialog = mapping[let]; //let is some int

插入该值,如:

 mapping[let] = newDialog2;

我该如何使用地图?例如,differenttypes采用字符串、int等。也许使用boost::变体?

您可以使用并集和指示并集实际包含的内容的"类型标记"(枚举或字符串)。假设您想要保存字符串、int和浮点:

union valU { float f; int i; char *s; };
enum valE { fl, in, st };
struct variousT { valU val; valE type; };
void print(variousT v)
{
   switch(v.type)
   {
      case fl: printf("%f", v.val.f); break;
      case in:  printf("%d", v.val.i); break;      
      case st:  printf("%s", v.val.s); break;
   }
}

当然,print可以是一个成员函数,variousT中应该有重载的setter,它们将标记与值等一起设置。但这是原始机制。

您可以使用boost在映射容器(或您喜欢的任何其他容器)中提供的any类型http://www.boost.org/doc/libs/1_60_0/doc/html/any.html

boost::任何类都支持复制任何值类型,并严格根据其类型对该值进行安全检查提取。

要获得有关元素类型的实现特定信息,请使用boost::any 的以下功能成员

 const std::type_info & type() const;

这里的示例(使用std::list):http://www.boost.org/doc/libs/1_60_0/doc/html/any/s02.html

应该是最安全、最快捷的方法。

您可以实现自己的'any'类型(在struct中使用嵌套的union),并将其作为值存储在映射中。然而,像std::string这样的非原始类型在这里有点棘手。

以下是一些基本示例:

#include <sstream>
#include <algorithm>
#include <string>
#include <map>
struct any {
    enum any_type:char { string_t = 0, int_t = 1 };
    any(){
    }
    any(const any& a) {
        this->type = a.type;
        switch (this->type) {
            case any_type::string_t: new(&(this->str)) std::string(a.str); break;
            case any_type::int_t   : this->i = a.i; break;
            /* more types */
        }
    }
    ~any(){
        switch (this->type) {
            case any_type::string_t: { if (str.size()) { str.std::string::~string(); } } break;  
            /* more types */
            default: ;
        }
    }
    std::string descr() const {
        switch (this->type) {
            case any_type::string_t: { std::stringstream s; s << "string : " << str; return s.str(); }  
            case any_type::int_t   : { std::stringstream s; s << "int    : " << i; return s.str(); }
            /* more types */
        }
    }
    any_type type;
    union {
        std::string str;
        int i;
        /* more types */
    };
};
using any_t = any::any_type;
int main() {
    std::map<std::string,any> m;
    any a;
    a.type = any_t::string_t;
    new(&(a.str)) std::string("aaa");
    //a.str = std::string{"aaa"};
    m.insert({"a",a});
    any b;
    b.type = any_t::int_t;
    b.i = 5;
    m.insert({"b",b});
    for(auto& a : m) {
        std::cout << a.second.descr() << "n";
    }
    return 0;
}