Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
292 views
in Technique[技术] by (71.8m points)

c++ - Is it possible to define enumalpha?

I would like to be able to write:

cout << enumalpha << Monday;

and get printed on console:

Monday

P.S. Monday is an enum type.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Okay, let's go all preprocessor then :)

Intended way of use:

DEFINE_ENUM(DayOfWeek, (Monday)(Tuesday)(Wednesday)
                       (Thursday)(Friday)(Saturday)(Sunday))

int main(int argc, char* argv[])
{
  DayOfWeek_t i = DayOfWeek::Monday;
  std::cout << i << std::endl;            // prints Monday

  std::cin >> i >> std::endl;             // reads the content of a string and
                                          // deduce the corresponding enum value
}

Dark magic, involving the helpful Boost.Preprocessor library.

#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/stringize.hpp>
#include <boost/preprocessor/seq/enum.hpp>
#include <boost/preprocessor/seq/for_each.hpp>

#define DEFINE_ENUM_VAL_TO_STR(r, data, elem)                      
   case BOOST_PP_CAT(data, BOOST_PP_CAT(::, elem)):                
    return out << BOOST_PP_STRINGIZE(elem);

#define DEFINE_ENUM_STR_TO_VAL(r, data, elem)                      
   if (s == BOOST_PP_STRINGIZE(elem))                              
   { i = BOOST_PP_CAT(data, BOOST_PP_CAT(::, elem)) ; } else


#define DEFINE_ENUM(Name, Values)                                  
   struct Name {                                                   
     enum type {                                                   
       Invalid = 0,                                                
       BOOST_PP_SEQ_ENUM(Values)                                   
     };                                                            
   };                                                              
   typedef Name::type Name##_t;                                    
   std::ostream& operator<<(std::ostream& out, Name##_t i) {       
    switch(i) {                                                    
      BOOST_PP_SEQ_FOR_EACH(DEFINE_ENUM_VAL_TO_STR, Name, Values)  
    default: return out << "~"; } }                                
   std::istream& operator>>(std::istream& in, Name##_t& i) {       
     std::string s; in >> s;                                       
     BOOST_PP_SEQ_FOR_EACH(DEFINE_ENUM_STR_TO_VAL, Name, Values)   
     { i = Name##::Invalid; } }

There are better ways, personally I use this little macro to store that all in a nicely sorted vector of pairs, static for the type, it also allows me to iterate through the values of the enum if the mood (or need) strikes :)

It's quite unfortunate though there is no support in the language for that. I would prefer if there was, enum are quite handy for codesets...


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...