Enumeration type that can be converted from int to string and from string to int

Asked 2 years ago, Updated 2 years ago, 39 views

In C++, you created an enumeration that can convert from int to string or from string to int.

#defineENUM(name,...)\
US>class name
    public:\
    enum Tag {__VA_ARGS__};\
    \
    private:\
    static std::unordered_map<int, std::string>_intToStringMap;\
    static std::unordered_map<std::string, int>_stringToIntMap;\
    public:\
    static std::string toString(inti){\
        if(_intToStringMap.empty())
            std::string args=#__VA_ARGS__;\
            createMap(_intToStringMap,_stringToIntMap, args);\
        } \
        autoit=_intToStringMap.find(i);\
        if(it!=_intToStringMap.end())
            return it ->second;\
        } else
            US>";\
        } \
    } \
    static int to Int(const std::string & str)
        if(_stringToIntMap.empty())
            std::string args=#__VA_ARGS__;\
            createMap(_intToStringMap,_stringToIntMap, args);\
        } \
        autoit=_stringToIntMap.find(str);\
        if(it!=_stringToIntMap.end())
            return it ->second;\
        } else
            return 0;\
        } \
    } \
};

void createMap(std::unordered_map<int, std::string>&intToStringMap,
               std::unordered_map<std::string, int>&stringToIntMap,
               const std::string & args)
{
    std::string trimmed = ESCUtils::trim(args);
    std::vector<std::string>split=ESCUtils::split(trimmed, ", ");
    int index = 0;
    for(const std::string & s:split)
        std::vector<std::string>vect=ESCUtils::split(s, "=");
        std::string str =vect.front();
        if(vect.size()>=2){
            index=ESCUtils::stoi(vect.at(1));
        }
        intToStringMap.insert(std::make_pair(index,str)));
        US>stringToIntMap.insert(std::make_pair(str,index));
        index++;
    }
}

Trim is a function that returns a blank character, a string without a new line, and split is a function that splits the string with the specified character and returns a vector.

Use Cases

ENUM (RoomIndex,
     Room 0 = 0,
     Room1,
     Room2,
     Room 3,
     Shower,
     ShowerOpen,
     Toilet,
     ToiletBowl,
     ToiletTop,
     ToiletSide,
     ToiletPaper,
     Mirror,
     LeftDrawer,
     RightDrawer,
     TowelRing,
     WallPaper,
     WallHole,
     Corner,
     Washing Machine,
     Bars,
     )

Now that I've used this,

Undefined symbols for architecture arm64:
  "RoomIndex::_stringToIntMap", referenced from:
      RoomIndex::toString(int) in ESCMainGameLayer.o
  "RoomIndex::_intToStringMap", referenced from:
      RoomIndex::toString(int) in ESCMainGameLayer.o
ld —symbol(s) not found for architecture arm 64
clang:error:linker command failed with exit code 1 (use-v to see invocation)

A build error was displayed.
How can I fix it?

xcode c++

2022-09-30 16:15

2 Answers

The static member variable written in the class definition is only a "declaration" and there is no "definition."

static std::unordered_map_intToStringMap;\
static std::unordered_map_stringToIntMap;\

These two are not definitions by themselves, so you need to give variable definitions outside of the class definition.
US>Out of Macros classDefinitions

std::unordered_map name::_intToStringMap;\
std::unordered_map name::_stringToIntMap;\

If so, the undefined symbol beyond "for now" should be resolved.

"First of all" is due to the following problems.

The definition of a static member variable in the header file violates the ODR.
This ENUM macro is supposed to be used in the header file, but
Multiple ***.cpp to use the same ENUM macro to materialize multiple static member variables, so
Another link error duplicate symbol will occur.

Hmm...
template If I fix it to the base, it will become weak symbol and there will be no problem... What do you think?
When multiple identical functions are defined in the template function
I can't afford to think about the implementation now, so I'll leave the implementation to someone else.


2022-09-30 16:15

Corrected as follows and resolved.

#defineENUM(name,...)\
US>class name
    public:\
    enum Tag {__VA_ARGS__};\
    \
    private:\
    static std::unordered_map<int, std::string>&getIntToStringMap()
        static std::unordered_map<int, std::string>_intToStringMap;\
        return_intToStringMap;\
    } \
    static std::unordered_map<std::string, int>&getStringToIntMap()
        static std::unordered_map<std::string, int>_stringToIntMap;\
        return_stringToIntMap;\
    } \
    static void createMap(conststd::string & args)
        std::string trimmed = ESCUtils::trim(args);\
        std::vector<std::string>split=ESCUtils::split(trimmed,",");\
        int index = 0;\
        for(const std::string & s:split)
            std::vector<std::string>vect=ESCUtils::split(s, "=");\
            std::string str =vect.front();\
            if(vect.size()>=2){\
                index=ESCUtils::stoi(vect.at(1));\
            } \
            getIntToStringMap().insert(std::make_pair(index,str));\
            getStringToIntMap().insert(std::make_pair(str,index));\
            index++;\
        } \
    } \
    public:\
    static std::string toString(inti){\
        if(getIntToStringMap().empty())
            std::string args=#__VA_ARGS__;\
            createMap(args);\
        } \
        autoit=getIntToStringMap().find(i);\
        if(it!=getIntToStringMap().end())
            return it ->second;\
        } else
            US>";\
        } \
    } \
    static int to Int(const std::string & str)
        if(getStringToIntMap().empty())
            std::string args=#__VA_ARGS__;\
            createMap(args);\
        } \
        autoit=getStringToIntMap().find(str);\
        if(it!=getStringToIntMap().end())
            return it ->second;\
        } else
            return 0;\
        } \
    } \
};


2022-09-30 16:15

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.