I personally use an enhanced enum because I've always found the enum of C++ lacking: messages like Type 3 - method -begin aren't much informative.
To this way, I use a simple templated class:
template <class Holder> class Enum { public: typedef typename Holder::type enum_type; Enum(): mValue(Invalid()) {} Enum(enum_type i): mValue(Get(i)) {} explicit Enum(const std::string& s): mValue(Get(s)) {} bool isValid() const { return mValue != Invalid(); } enum_type getValue() const { return mValue->first; } private: typedef typename Holder::mapping_type mapping_type; typedef typename mapping_type::const_iterator iterator; static const mapping_type& Mapping() { static mapping_type MMap = Holder::Initialize(); return MMap; } static iterator Invalid() { return Mapping().end(); } static iterator Get(enum_type i) { // search } static iterator Get(const std::string& s) { // search } iterator mValue; };
You define Holder like so:
struct Example { typedef enum { Value1, Value2, Value3 } type; typedef std::vector< std::pair< type, std::string > > mapping_type; static mapping_type Initialize() { return builder<mapping_type>()(Value1,"Value1")(Value2,"Value2")(Value3,"Value3"); } };
You can define a macro for it:
DEFINE_ENUM(Example, (Value1)(Value2)(Value3))
But I let the implementation as an exercise (Boost.Preprocessor is your friend).
The cool thing is to use it!
int main(int argc, char* argv[]) { std::string s; std::cin >> s; Enum<Example> e(s); switch(e.getValue()) { case Example::Value1: case Example::Value2: ++e; case Example::Value3: std::cout << e << std::endl; default: } }