vendredi 15 juillet 2022

Creating static map in C++ class [duplicate]

I am trying to create a std::map which maps an enum to a string (an enum of database types and their type name strings).

I have a enum class with each type, and a class with two public static function to convert from type to string and string to type.

If I make the definition of the map static I get the error a static data member with an in-class initializer must have non-volatile const integral type or be specified as 'inline' (I can't use inline because I am stuck with C++11)

Header file:

enum class DBDataType {
    Unset,
    Boolean,
    Character,
    Date,
    Double,
    Integer,
    Time,
    TimeStamp,
};

class DB_DT {
public:
    static std::string Type2Str(DBDataType type);
    static DBDataType Str2Type(std::string name);
private:
    static std::map<DBDataType, std::string> typeStringMap {
        {DBDataType::Boolean, "BOOLEAN"},
        {DBDataType::Character, "CHAR"},
        {DBDataType::Date, "DATE"},
        {DBDataType::Double, "DOUBLE"},
        {DBDataType::Integer, "INTEGER"},
        {DBDataType::Time, "TIME"},
        {DBDataType::TimeStamp, "TIMESTAMP"},
    };
    DB_DT();
};

CPP File:

std::string DB_DT::Type2Str(DBDataType type)
{
    auto pos = typeStringMap.find(type);
    if (pos == typeStringMap.end()) {
        return "";
    }
    else {
        return pos->second;
    }
}

DBDataType DB_DT::Str2Type(std::string name)
{
    for (auto it = typeStringMap.begin(); it != typeStringMap.end(); ++it) {
        if (it->second.compare(name)) {
            return it->first;
        }
    }
    return DBDataType::Unset;
}

So I changed the header declaration to static std::map<DBDataType, std::string> typeStringMap; create a function to fill the map if it is empty, which is checked from the converter functions:

std::string DB_DT::Type2Str(DBDataType type)
{
    if (typeStringMap.empty()) {
        createMap();
    }

    auto pos = typeStringMap.find(type);
    if (pos == typeStringMap.end()) {
        return "";
    }
    else {
        return pos->second;
    }
}

DBDataType DB_DT::Str2Type(std::string name)
{
    if (typeStringMap.empty()) {
        createMap();
    }

    for (auto it = typeStringMap.begin(); it != typeStringMap.end(); ++it) {
        if (it->second.compare(name)) {
            return it->first;
        }
    }
    return DBDataType::Unset;
}

void DB_DT::createMap()
{
    typeStringMap.emplace(DBDataType::Boolean, "BOOLEAN");
    typeStringMap.emplace(DBDataType::Character, "CHAR");
    typeStringMap.emplace(DBDataType::Date, "DATE");
    typeStringMap.emplace(DBDataType::Double, "DOUBLE");
    typeStringMap.emplace(DBDataType::Integer, "INTEGER");
    typeStringMap.emplace(DBDataType::Time, "TIME");
    typeStringMap.emplace(DBDataType::TimeStamp, "TIMESTAMP");
}

Which gives me the helpful error LNK2001: unresolved external symbol "private: static class std::map<DBDataType, std::string>

I don't understand this linking error, what exactly is wrong with this implementation? Would I be better off moving the definition of the map outside of the class?

Aucun commentaire:

Enregistrer un commentaire