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

C++ unordered_map especify types on runtime

本文关键字:类型 运行时 unordered map c++      更新时间:2023-10-16

是否有任何方法可以定义一个unordered_map<*,*> var,并根据情况或其他重新定义它与适当的类型?

我正在阅读一些二进制文件,每个文件的格式都不一样,所以根据格式它可以通过<int, string>, <short, string>, <int, int>, etc..

我能想到的唯一方法是定义它<char *, char *>,但我必须定义哈希和其他类似的东西。

还有其他选择吗?

编辑。为问题添加更多上下文:

我将迭代另一个列表并从ordered_maps中获取值,我将知道我为键使用什么类型的数据,并使用它来生成JSON字符串作为结果。

对于更多上下文,文件的格式如下:

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

您将在地图中存储什么?您将如何选择它?

你的问题有两个可行的解决方案:

参数多态性

这是你首先应该尝试解决问题的方法。通过保持你的unordered_map的参数是通用的

这主要是通过像

这样的结构来实现的
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;
  }
};

子类型多态性

定义你自己的Key和/或Value类,这样你就可以定义一个std::unordered_map<Key*,Value*>,然后用你需要的类型来子类型这些自定义类型。

如果不知道这些将如何使用,就很难判断哪些是最好的。

我最终使用自定义类型和void *作为数据。

所以我在结构体中设置了var的类型和它的数据。

结果如下:

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