简体   繁体   English

C ++ unordered_map在运行时指定类型

[英]C++ unordered_map especify types on runtime

Is there any way that I could define an unordered_map<*,*> var and depending a case or other redefine it with the appropriate types? 有什么方法可以定义unordered_map<*,*> var并根据大小写或其他方式使用适当的类型对其进行重新定义?

I'm reading some binaries files and the format is different for each so depending the formats it can by <int, string>, <short, string>, <int, int>, etc.. 我正在读取一些二进制文件,每个文件的格式都不同,因此取决于<int, string>, <short, string>, <int, int>, etc..的格式<int, string>, <short, string>, <int, int>, etc..

The only way I can think of is to define it <char *, char *> but I would have to define the hashing and other thing to work like that. 我能想到的唯一方法是定义它<char *, char *>但是我必须定义散列和其他类似的功能。

Is there any other option? 还有其他选择吗?

EDIT. 编辑。 ADD MORE CONTEXT FOR THE PROBLEM: 为问题添加更多上下文:

I will iterate another lists and get the values from the ordered_maps, I will know what type of data I'm using for the key and use that to generate a JSON string as result. 我将迭代另一个列表并从ordered_maps中获取值,我将知道我将用于密钥的数据类型,并使用该数据类型生成JSON字符串作为结果。

For more context the format of the files are like these: 有关更多上下文,文件的格式如下:

INT number of fields to use. Example: 3
-- now there is a for from 1 to 3 as we have 3 fields
CHAR type of data (1 = int8, 2 = int16, 3 = int32, 4=string)
STRING name of the field
STRING alias of the field
-- end for
-- now I do a while not EOF
    -- for each field
        read value from file (int8, int16, int32, string) depending the type of field
        first item of the for will be the KEY
        if item != first add the value to an unoredered_map using the first as key
    -- end for
-- end while

What are you going to store inside the map and how are you going to choose it? 您将在地图内存储什么以及如何选择它?

There are two practical solution to your problem: 有两种实用的解决方案可以解决您的问题:

Parametric Polymorphism 参数多态

This is how you should try to solve your problem in the first place. 这就是您应该首先尝试解决问题的方式。 By keeping the arguments of your unordered_map generic. 通过保持您的unordered_map的参数通用。

This is mostly done by having a structure like 这主要是通过具有类似

class Reader {
  virtual void readFile(const std::string& name) = 0;
};

template<typename K, typename V>
class RealReader {
private:
  std::unordered_map<K,V> data;

public:
  void readFile(const std::string& name) override {
    K key = // read key;
    V value = // read value
    data[key] = value;
  }
};

Subtype Polymorphism 亚型多态性

Define your own Key and/or Value classes so that you can define a std::unordered_map<Key*,Value*> and then subtype these custom types with your required types. 定义自己的Key和/或Value类,以便可以定义std::unordered_map<Key*,Value*> ,然后用所需的类型将这些自定义类型子类型化。

Without knowing how these are going to be used it's difficult to tell what's best. 不知道这些将如何使用,很难说出什么是最好的。

I ended up using a self defined type and void * for the data. 我最终使用了一个自定义类型,并为数据使用了void *。

So I set the type of the var in the struct and the data for it. 因此,我在结构中设置了var的类型及其数据。

Here is the result: 结果如下:

struct fieldVariant {
    char type;
    void * data;
    fieldVariant(char _type, void * _data) {
        type = _type;
        data = _data;
    }
};
struct fieldHash {
    inline size_t operator()(const fieldVariant * val) const
    {
        unsigned long h = 0;
        unsigned long varSize = 0;
        switch (val->type) {
            case INT8:
                varSize = 1;
                break;
            case INT16:
                varSize = 2;
                break;
            case INT32:
                varSize = 4;
                break;
            case INT64:
                varSize = 8;
                break;
            case INT128:
                varSize = 16;
                break;
            case CHAR2:
                varSize = ((string *)val->data)->length();
                break;
        }

        for (int i=0; i < varSize; i++)
            h = 5 * h + *(char *)(val->data + i);
        return size_t(h);
    }
};


struct fieldEql {
    inline bool operator()(const fieldVariant *s1,const fieldVariant *s2) const {
        unsigned long varSize = 0;
        switch (s1->type) {
            case INT8:
                varSize = 1;
                break;
            case INT16:
                varSize = 2;
                break;
            case INT32:
                varSize = 4;
                break;
            case INT64:
                varSize = 8;
                break;
            case INT128:
                varSize = 16;
                break;
            case CHAR2:
                return *((string *)s1->data) == *((string *)s2->data);
        }
        return memcmp(s1->data, s2->data, varSize) == 0;
    }
};

unordered_map<fieldVariant *, fieldVariant *, fieldHash, fieldEql> data;
void add(fieldVariant * key, fieldVariant * value) {data[key] = value;};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM