how print enums?

see these enum:
1
2
3
4
5
6
7
8
9
10
enum TokenType
    {
        ID=0,
        KeyWord=1,
        Operator=2,
        Expression=3,
        String=4,
        Number=5,
        Char=6
    };

when i do:
cout<< TokenType::ID;
it will print zero... is there anyway for print 'ID' instead zero?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>
#include <string>
using namespace std;

enum TokenType
{
   ID=0,
   KeyWord=1,
   Operator=2,
   Expression=3,
   String=4,
   Number=5,
   Char=6
};

ostream &operator << ( ostream& strm, TokenType tt )
{
   const string nameTT[] = { "ID", "KeyWord", "Operator", "Expression", "String", "Number", "Char" };
   return strm << nameTT[tt];
}


int main()
{
   TokenType tt = TokenType::Expression;
   cout << tt << '\n';
   cout << TokenType::Expression << '\n';
   cout << TokenType::ID << '\n';
}
Yes, operator overloading:
1
2
3
4
5
6
7
8
9
10
11
std::ostream& operator<<(std::ostream& os, const TokenType Token)
{
  switch(Token)
  {
    case TokenType::ID:
      os << "ID";
    break;
    case ...
  }
  return os;
}
thank you so much for all... thank you.
is what i need
PS: i used 'friend', because is inside a class ;)
Last edited on
Enums are one of those things which break the ODR, unless you program them carefully. There is actually a macro trick (called, unsurprisingly, the “enum macro trick”) which people who know their stuff use.

First, declare your enumerated values using a macro form:

1
2
3
4
5
6
7
8
#define TOKEN_TYPES( F ) \
  F(ID) \
  F(KeyWord) \
  F(Operator) \
  F(Expression) \
  F(String) \
  F(Number) \
  F(Char) 

Now you need to instantiate the enum proper, which should be in the same place as your TOKEN_TYPES macro (the .hpp file):

1
2
3
#define F(name) name ,
enum token_types { TOKEN_TYPES( F ) NumTokenTypes };
#undef F 

You should also declare a couple of functions to transform those enums to or from strings:

1
2
std::string token_type_to_string( token_types );
token_types string_to_token_type( const std::string& );

In your source (.cpp file) you can now instantiate both the lookup table and the functions to do the look ups for the user:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#define F(name) #name ,
const char* token_type_names[] = { TOKEN_TYPES( F ) nullptr };
#undef F

std::string token_type_to_string( token_types token )
{
  return ((int)token < (int)NumTokenTypes)
    ? token_type_names[ (int)token ]
    : "";
}

token_types string_to_token_type( const std::string& s )
{
  return std::find( token_type_names, token_type_names + NumTokenTypes, s ) - token_type_names;
  // You could raise an exception if the above expression == NumTokenTypes, if you wanted
}

Whatever else you provide is up to you (such as << and >> operator overloads).

This is a very simple version of the Enum Macro Trick. You can do all kinds of fun and interesting things with it, such as providing multiple data per enum, instantiating it as a different type (not necessarily an enum, but as any kind of constant value, or a std::map lookup, or whatever).

When using a strictly 0..N valued-enum, the number of items in the enum is easy (as demonstrated above). But you can even provide an F() macro which simply counts the number of elements:

1
2
3
#define F(...) + 1
auto NumTokenTypes = TOKEN_TYPES( F );
#undef F 

Hope this helps.

Disclaimer: I just typed this all off the top of my head. Dumb typos or mistakes could have been made.
thank you so much for all
you make work contracts("Disclaimer: ...." with a little letters) :P
thank you so much for all
Topic archived. No new replies allowed.