Enum with name string, best implementation

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Ian Simpson
    New Member
    • Jan 2011
    • 11

    Enum with name string, best implementation

    Hi Everyone,

    I've been browsing around for solutions to how to have an enum that gives me a name string. Some rather complicated ones can be found on the gamedev forum and Code Project.

    I am thinking about simply writing a script that takes a list of names and generates a class like so.
    Code:
    class GangstaEnum
    {
    public:
       int VanillaIce = 0;
       int MrT = 1;
       int MrRogers = 2;
    
       char* get_str(int idx){return gangstas[idx];}
    
    private:
       char[3] gangstas = {"VanillaIce", "MrT"};
    and then just using the class like an enum. The downside is that I would have to rerun my script every time the list changed. The upside is that its extremely simple.

    Does anyone know why I should favor more complicated methods using macros or STL maps? God didn't give me enough patience for Macros.
  • weaknessforcats
    Recognized Expert Expert
    • Mar 2007
    • 9214

    #2
    I would use an STL vector and put all of my strings in there. Then I can use the find algorithm to locate a string. The algorithm will return an iterator to your string. The iterator is a pointer to your string.

    Comment

    • Ian Simpson
      New Member
      • Jan 2011
      • 11

      #3
      I don't like that as much. People will be using my code in a library and I like them to be able to see all the possible members somehow.

      Thanks for the reply though

      Comment

      • weaknessforcats
        Recognized Expert Expert
        • Mar 2007
        • 9214

        #4
        An enum is just a named integer value. It's not an actual variable. That means using an enum is a compile-time activity.

        The fact you developed a class leads me to believe you have a run-time requirement rather than a compile time requirement.

        If you need to use your own class at run time, then you mught consider Singleton objects with a registry.

        Comment

        • Ian Simpson
          New Member
          • Jan 2011
          • 11

          #5
          In a simple eample, the user code will be calling a method send:
          Code:
          Library::send(MsgType, MsgData);
          There are about 400+ possible message types. Inside the library method I need to convert the MsgType argument into the corresponding string.

          So perfect scenario, the user (in the code, not during run-time) passes a custom type that displays all options (in vs with intellisense) and is restricted to those options, and then that custom type can be converted to string within library.

          An Enum will restrict values and display all types, but not convert to string. My class will display all values and convert to string, but not restrict values. I believe a macro would do all three but be a pain-in-the-you-know-what and could confuse future coders as well as myself.

          Comment

          • weaknessforcats
            Recognized Expert Expert
            • Mar 2007
            • 9214

            #6
            Try this:

            Code:
            class Message
            {
               virtual void ReadMessage();
            
            };
            class LunchTime : public Message
            {
                 virtual void ReadMessage();
            
            };
            
            class Temperature : public Message
            {
                 virtual void ReadMessage();
            
            };
            
            
            Then in main() you:
            
            Message* data = new LunchMessage("Louie's as 12:00");
            
            data->ReadMessage();  //calls LunchMessage::ReadMessage
            
            delete data;
            
            data = new Temperature(45);
            
            data->ReadMessage(); calls Temperature::ReadMessage
            By setting up a polymorphism your 400 message types become derived classes and each derived class knows how to format it's own message. Then in the user code you create a derived object but use it as a base class pointer.

            That means the classes know how to format their messages. And that means you don't need to do that yourself. Your enum approach looks something you might use in C where no object-oriented features exist.

            The trick is substituting a derived class pointer as the argument to a function expecting a base class pointer. The virtual keyword insure the derived class method is called.

            What do you think?

            Comment

            • Ian Simpson
              New Member
              • Jan 2011
              • 11

              #7
              Thanks Mr. cats, the replies helped me process my options. I think the final code will have an enum wrapped in a class with a string array, and I'll force the user to access the enum through the class and use the class like a virtual singleton.

              Your suggestion is perfect, but the example I gave was over-simplified; in this case the message with 400+ types is already inheriting from a message base class and a type in its own right. So I've actually already implemented your suggestion in one layer.

              Comment

              • weaknessforcats
                Recognized Expert Expert
                • Mar 2007
                • 9214

                #8
                Your problem will be that to add a message you will have to change your class by adding a new enum and a new string and a new format converter. Should you have your code installed on user computers you will need to upgrade every one of them.

                By using polymorphism, you just add a new class and recompile. None of the older code needs to be changed. This is the beauty of polymorphism. Code written in 1990 when no one had every heard of MESSAGE_FROM_WE ANESSFORCATS can be used to process those messages. You just create a derived object and send it's address into your old code as a base class address and your old code will call your new object. Think about it

                Comment

                • Ian Simpson
                  New Member
                  • Jan 2011
                  • 11

                  #9
                  Wait, I might be a little confused, but it seems to me that in both cases you have to recompile and redistribute the library. In one case I add an enum and an element to the string array, and in the other you add a class. These message subtypes need no different formatting methods or members different from the other subtypes and I can't see how the user code would be impacted by adding a couple of elements to the class.

                  If these message types did, on the other hand, require unique members and methods from each other, then another layer of abstraction would definitely be in order.

                  Comment

                  • weaknessforcats
                    Recognized Expert Expert
                    • Mar 2007
                    • 9214

                    #10
                    Keep in mind that your library would contain functions whose arguments were pointers to base class objects. Therefore, the library never needs recompiling. You only recompile the program thet uses the library.

                    Comment

                    • Ian Simpson
                      New Member
                      • Jan 2011
                      • 11

                      #11
                      Only if the user is defining the child classes, right? In my case the child classes will be defined within the library.

                      Comment

                      • weaknessforcats
                        Recognized Expert Expert
                        • Mar 2007
                        • 9214

                        #12
                        Then you are back to using a vector or perhaps a map if you need am integer value to identify a string:

                        Code:
                        map<enum value, string> MyMessages;
                        You could just call a function at the beginning of
                        main() to load the map from a text file that contains the enum value and the associated string.

                        Or use the singleton class you are thinking about anyway. You would load the map in the singleton constructor by calling the same function you would have called at the beginning of main().

                        If you use a map then you add messages by modifying a data file and not your code. The preferred approach is to not modify already written and debugged code.

                        Comment

                        Working...