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?
static
in your cpp file, you can initialise it there as well (though be aware of the initialisation order)if
s. Have I misunderstood something?