Ответ 1
#define ENUM_MEMBER(MEMBER) \
, MEMBER
#define ENUM_FROM_STRING(MEMBER) \
if(str == #MEMBER ) return MEMBER;
#define ENUM_TO_STRING(MEMBER) \
case MEMBER: return #MEMBER;
#define CREATE_ENUM_1(NAME,MACRO,DEFAULT) \
class NAME { \
public: \
enum E { \
DEFAULT \
MACRO(ENUM_MEMBER) \
}; \
protected: \
E _value; \
public: \
NAME() { _value = DEFAULT; } \
NAME(const NAME& copy) { _value = copy._value; } \
NAME(const char ch[]) : NAME(string(ch)) {} \
NAME(const string& s) { _value = fromString(s); } \
NAME(const E en) \
{ if(!isValid(en)) _value = DEFAULT; else _value = en; } \
\
NAME& operator=(const NAME& r) \
{ \
if(this != &r) \
_value = r._value; \
return *this; \
} \
\
NAME& operator=(const NAME::E& r) \
{ \
_value = r; \
return *this; \
} \
\
bool operator==(const NAME::E& r) const { return _value == r; } \
bool operator!=(const NAME::E& r) const { return _value != r; } \
bool operator==(const NAME& r) const { return _value == r._value; } \
bool operator!=(const NAME& r) const { return _value != r._value; } \
string operator+(const string& r) const { return toString() + r; } \
NAME::E value() const { return _value; } \
\
string toString() const { return name(_value); } \
NAME::E fromString(const string& str) \
{ _value = parse(str); return _value; } \
\
static vector<NAME> getVector() \
{ \
static vector<NAME> vec = { DEFAULT MACRO(ENUM_MEMBER) }; \
return vec; \
} \
\
static E getDefault() { return E::DEFAULT; } \
static string name(const NAME::E e) \
{ \
switch( e ) { \
MACRO(ENUM_TO_STRING) \
default: return #DEFAULT; \
} \
} \
\
static E parse(const string& str) \
{ \
MACRO(ENUM_FROM_STRING) \
return E::DEFAULT; \
} \
\
static size_t count() \
{ \
static E all[] = { DEFAULT MACRO(ENUM_MEMBER) }; \
return sizeof(all) / sizeof(E); \
} \
\
static bool isValid(const string& str) \
{ \
E e = parse(str); \
if(e == E::DEFAULT && str != #DEFAULT) \
return false; \
return true; \
} \
\
static bool isValid(const int val) \
{ \
string s = name((NAME::E)val); \
if(s == #DEFAULT && val != E::DEFAULT) \
return false; \
return true; \
} \
};\
string operator+(const string& l, const NAME& en); \
std::ostream& operator<<(std::ostream& s, const NAME& en); \
std::istream& operator>>(std::istream& s, NAME& en);
#define CREATE_ENUM_2(NAME,DEFAULT) \
CREATE_ENUM_1(NAME,NAME##_Members,DEFAULT)
#define CREATE_ENUM(NAME,DEFAULT) \
CREATE_ENUM_2(NAME,DEFAULT)
используйте этот макрос в исходном коде, чтобы избежать ошибки связи:
#define CREATE_ENUM_CPP(NAME) \
string operator+(const string& l, const NAME& en) { return l + en.toString(); } \
std::ostream& operator<<(std::ostream& s, const NAME& en) { s << en.toString(); return s;} \
std::istream& operator>>(std::istream& s, NAME& en) { string t; s >> t; en.fromString(t); return s;}
Использование
#define Animal_Members(ENUM) \
ENUM(DOG) \
ENUM(CAT) \
ENUM(COW) \
CREATE_ENUM(Animal,None)
// in source code:
CREATE_ENUM_CPP(Animal)
TEST
cout << Animal::parse("CAT") << endl;
cout << Animal::parse("INVALID STRING") << endl;
cout << Animal::name(Animal::CAT) << endl;
auto vec = Animal::getVector();
for(auto it = vec.begin(); it != vec.end() ; ++it)
cout << *it << endl;
Animal cat = "CAT", DOG = "DOG";
cout << "(cat == DOG): " << (cat == DOG) << endl;
Animal a = "CAT";
string string_concat = "VALUE: " + a;
cout << string_concat << endl;
cin >> a;
cout << "INPUT: " << a << endl;
cout << "defalut=" << Animal(Animal::getDefault()) << endl;
Animal d("DOG"); // string init
d = "COW"; // string assignment;
d = Animal::CAT; // enum assginment;
Animal e = d; //copy constructor
cout << "(e == d): " << (e == d) << endl; // compare