我希望能够写下:
cout << enumalpha << Monday;
并在控制台上打印:
周一
P.S。星期一是枚举类型。
答案 0 :(得分:8)
好的,让我们去所有预处理器然后:)
预期使用方式:
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
}
黑魔法,涉及有用的Boost.Preprocessor库。
#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; } }
还有更好的方法,我个人用这个小宏来存储所有在一对排序很好的矢量对,静态的类型,它还允许我迭代枚举的值,如果心情(或需要)罢工:)
虽然没有语言支持,但这是非常不幸的。我希望如果有的话,枚举对于代码集来说非常方便......
答案 1 :(得分:4)
据我所知,你想要的确切形式是不可能的。正如尼尔所说,名字对我们来说仅仅是人类;编译器处理值。
也就是说,您可以创建一个实用程序来为枚举命名。这是一个例子:
#define ENUM_NAMES_BEGIN(pType) \
std::ostream& operator<<(std::ostream& pStream, pType pValue) \
{ \
switch (pValue) \
{
#define ENUM_NAMES_CASE_NAMED(pValue, pName) \
case (pValue): \
pStream << (pName); \
break;
#define ENUM_NAMES_CASE(pValue) ENUM_NAMES_CASE_NAMED(pValue, #pValue)
#define ENUM_NAMES_END(pDefault) \
default: \
pStream << (pDefault); \
} \
\
return pStream; \
}
你可以这样使用它:
#include <iostream>
enum Days
{
Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday
};
enum NotNamed
{
DontTry, ImNotnamed
};
ENUM_NAMES_BEGIN(Days)
ENUM_NAMES_CASE(Sunday)
ENUM_NAMES_CASE(Monday)
ENUM_NAMES_CASE(Tuesday)
ENUM_NAMES_CASE(Wednesday)
ENUM_NAMES_CASE(Thursday)
ENUM_NAMES_CASE(Friday)
ENUM_NAMES_CASE_NAMED(Saturday, "Saturday: Fun day!")
ENUM_NAMES_END("")
int main()
{
Days d = Saturday; // or whatever
NotNamed n = ImNotnamed;
std::cout << "Day: " << d << std::endl;
std::cout << "Not Named: " << n << std::endl;
}
使用“未命名”类型尝试返回其数值。
注意,这里实际上没有强制执行枚举;例如,您可以使用它来命名整数值。如果你这样做,operator<<
就会含糊不清。
如果你可以使用Boost,使用他们的类型特征is_enum
(这是相当复杂的)和静态断言它是这种情况。为此,改变将是:
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_enum.hpp>
#define ENUM_NAMES_BEGIN(pType) \
std::ostream& operator<<(std::ostream& pStream, pType pValue) \
{ \
BOOST_STATIC_ASSERT(boost::is_enum<pType>::value); \
switch (pValue) \
{
现在,如果类型不是枚举,则编译错误至少指向您尝试定义枚举名称的行。
答案 2 :(得分:2)
(不,这不回答一般情况下的问题,但可能仍有人感兴趣)
正如Neil在对这个问题的评论中所说,在枚举的一般情况下,你不能这样做。但是,对于个别情况,您可以为流插入运算符(<<
)重载枚举类型:
#include <iostream>
enum day_of_week
{
friday,
saturday,
sunday
};
std::ostream& operator<<(std::ostream& o, day_of_week day)
{
switch (day)
{
case friday: o << "Friday"; break;
case saturday: o << "Saturday"; break;
case sunday: o << "Sunday"; break;
}
return o;
}
例如,使用上面的代码,这个:
std::cout << saturday << std::endl;
将打印:
Saturday