1

I want to convert char * to enum so I used this. But I am getting error while converting char * to enum

I cannot change my enum. Also type[] is dynamic for simplification I am showing static value.

enum type_t {
    MSG_1 = 0,
    MSG_2
};

char type[] = "MSG_1|MSG_2";
char *type_char;
type_char = strtok (type,"|");
while (type_char != NULL)
{
    type_t type_enum = static_cast<type_t >(type_char );
    type_char = strtok (NULL, "|;");
}

I am getting below error

error: invalid static_cast from type 'char*' to type 'type_t'

I want to convert char * to enum

Community
  • 1
  • 1
eswaat
  • 733
  • 1
  • 13
  • 31
  • 1
    `strtok()` is probably the worst choice :-( ... And `static_cast(type_char )` doesn't work, because these types are completely unrelated. – πάντα ῥεῖ Feb 18 '15 at 22:33
  • But I need to split my string in to "|" symbol. – eswaat Feb 18 '15 at 22:34
  • 1
    Consider more simple solution with defining array (or vector) of strings (or char *) and using enum as an index – VolAnd Feb 18 '15 at 22:34
  • Your code is *definitely* not valid C, and it is not valid C++; and yet, you've tagged both. `static_cast` implies you meant only the C++ tag, so please *only* use the language-appropriate tag. C != C++. – Tim Čas Feb 19 '15 at 00:36

4 Answers4

5

Unlike other languages that have stronger run-time "reflection" capabilities, in C++ enums are a purely compile-time artifact. Once the compiler is done, there is no way to get the names of enumeration constants. Debuggers can get them by reading special tables the compiler prepares for the debuggers, but it would be counterproductive to access these files.

If you want to be able to convert names of enumerations to their values, make a unordered_map from string to your enum, populate it statically, and perform lookups as needed:

static std::unordered_map<std::string,type_t> nameToTypeT;
...
nameToTypeT["MSG_1"] = MSG_1;
nameToTypeT["MSG_2"] = MSG_2;
...
type_t = nameToTypeT[std::string(type_char)];
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • my enum contain around 100 element for simplification I just mention 2 elements. Also char type[] is dynamic, for simplification I put static value. – eswaat Feb 18 '15 at 22:40
  • @eswaat There isn't much you can do - apart from using a macro for adding items to `nameToTypeT`, e.g. `#define ADD_ENUM_NAME(x) nameToTypeT[#x] = x` and using `ADD_ENUM_NAME(MSG_1); ADD_ENUM_NAME(MSG_2); ... ADD_ENUM_NAME(MSG_1000);` there are no simple tricks to make the task simple. It's perfectly OK to dynamic content in `type[]`, though. – Sergey Kalinichenko Feb 19 '15 at 00:27
2

You will have to write code that translates the text in the string into the relevant enum value.

I typically do this by writing a function along these lines:

type_t str_to_type_t(const char *str)
{
#define X(x) { #x, x }
  struct entry
  {
     const char *name;
     type_t value;
  };
  entry table[] = {
      X(MSG_1),
      X(MSG_2)
  };

  for(auto e : table)
  {
     if (strcmp(e.name, s) == 0)
       return e.value;
  }
  return -1;   // Or MSG_UNKNOWN or similar. 
}

If there are a large number of enums, then using a std::map<std::string, type_t> table; and then if ((auto it = table.find(s)) != table.end()) { return it->second; [or unordered_map, perhaps would be the better solution, but for a small number it makes little difference.

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
1

Here is an example:

struct entry_t
{
   type_t      value;
   const char *literal;
};
static const entry_t table[] =
{
   {MSG_1, "MSG1"},
   {MSG_2, "MSG2"},
};

type_t typeFromLiteral(const char *literal)
{
   for (size_t i = 0; i < sizeof(table)/sizeof(table[0]); ++i)
   {
     if (0 == strcmp(table[i].literal, literal))
     {
        return table[i].value;
     }
   };
   abort();
}
Valeri Atamaniouk
  • 5,125
  • 2
  • 16
  • 18
0

You can't cast from char * to enum, they are incompatible types. You have three options

  1. Use an

    if (strcmp(textualRepresentation, "EnumValue1") == 0)
         return EnumValue1;
    else if (strcmp(textualRepresentation, "EnumValue2") == 0)
         return EnumValue2;
    
  2. Create a struct containing both the textual representation and the value of the enum and then use bsearch() to match the textual representation and retrieve the enum value.

    struct EnumData {
        const char *name;
        Enum value;
    };
    
    EnumData enums[ENUM_COUNT] = {
        {"EnumValue1", EnumValue1},
        {"EnumValue2", EnumValue2}
    };
    
    int compare_enums(const void *const lhs, const void *const rhs)
    {
        return strcmp(reinterpret_cast<const EnumData *>(lhs)->name,
                      reinterpret_cast<const EnumData *>(rhs)->name);
    }
    

    and then search like this

    EnumData  key;
    void     *found;
    
    key.name = "EnumValue2";
    found    = bsearch(&key, enums, ENUM_COUNT, sizeof(EnumData), compare_enums);
    if (found != NULL)
        std::cout << reinterpret_cast<EnumData *>(found)->value << " is the enum value" << std::endl;
    
  3. Use std::map<const char *,Enum>, this is the best option.

The following code demonstrates the methods 2 and 3, method 1 is evident

enum Enum {
    InvalidEnumValue,
    EnumValue1,
    EnumValue2,
    EnumCount
};

struct EnumData {
    const char *name;
    Enum        value;
};

static EnumData enums[EnumCount] = {
    {"EnumValue1", EnumValue1},
    {"EnumValue2", EnumValue2},
    {"InvalidEnumValue", InvalidEnumValue}
};   

int compare_enums(const void *const lhs, const void *const rhs)
{
    return strcmp(reinterpret_cast<const EnumData *>(lhs)->name,
                  reinterpret_cast<const EnumData *>(rhs)->name);
}

Enum find_enum_value_with_bsearch(const char *const name)
{
    EnumData  key;
    void     *found;

    key.name = name;
    found    = bsearch(&key, enums, EnumCount, sizeof(EnumData), compare_enums);
    if (found == NULL)
        return InvalidEnumValue;
    return reinterpret_cast<EnumData *>(found)->value;
}


int
main()
{
    Enum                        value;
    std::map<const char *,Enum> enumsMap;

    enumsMap["EnumValue1"] = EnumValue1;
    enumsMap["EnumValue2"] = EnumValue2;

    value = find_enum_value_with_bsearch("EnumValue2");

    std::cerr << value << std::endl;
    std::cerr << enumsMap["EnumValue1"] << std::endl;
}
tcyrus
  • 50
  • 6
Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97