在用C++编写枚举时,我发现了一种模式。它是这样的:
class Player
{
public:
class State
{
public:
typedef enum
{
Stopped,
Playing,
Paused
}PossibleValues;
static const int Count() {return Paused+1;};
static const PossibleValues Default() {return Stopped;};
};
//...
}这解决了枚举中常见的一些问题,比如外部名称空间的污染等,但我仍然不喜欢这样: Count()是手动完成的。我只知道两种方法:一种是从Last+1计算出来的,一种是编写简单硬编码的。
问题是:是否有某种方式,比如使用预处理器宏,自动获取计数,将其放在Count()方法中?注意:我不想有最后一个假元素,叫做计数在枚举中,污染它!
提前感谢!
更新1:
关于更高级枚举的建议,在N4428枚举反射在标准C++11中的实现(部分)上有一个有趣的讨论。
更新2:
有趣的文档N 4451-静态反射(修订本3)的3.16,3.17,A.7,A.8节关于MetaEnums和MetaEnumClasses。
更新3:
在我看过限制-专业化#post444962之后,我使用枚举类找到了另一个有趣的模式。如果枚举类的枚举器列表是连续整数,通过定义其最大值和最小值,我们可以检查一个值是否属于它。
如果在Count()上使用Player::State方法的目的是检查一个值是否在枚举中,那么这个目的也是通过numeric_limits方法实现的,甚至更优越,因为它不需要枚举器列表以零值项开始!
enum class Drink
{
Water,
Beer,
Wine,
Juice,
};
#pragma push_macro("min")
#undef min
#pragma push_macro("max")
#undef max
namespace std
{
template <> class numeric_limits < Drink >
{
public:
static const/*expr*/ bool is_specialized = true;
static const/*expr*/ Drink min() /*noexcept*/ { return Drink::Water; }
static const/*expr*/ Drink max() /*noexcept*/ { return Drink::Juice; }
static const/*expr*/ Drink lowest() /*noexcept*/ { return Drink::Water; }
static const/*expr*/ Drink default() /*noexcept*/ { return Drink::Beer; }
};
}
#pragma pop_macro("min")
#pragma pop_macro("max")使用情况:
应用程序中的一个变量:
Drink m_drink;在构造函数中,其初始化为:
m_drink = numeric_limits<Drink>::default();对于表单的初始化,我可以这样做:
pComboDrink->SetCurSel(static_cast<int>(theApp.m_drink));在它上,为了使界面适应用户所做的更改,我可以使用限定作用域的枚举类值进行切换:
switch (static_cast<Drink>(pComboDrink->GetCurSel()))
{
case Drink::Water:
case Drink::Juice:
pAlcohoolDegreesControl->Hide();
break;
case Drink::Beer:
case Drink::Wine:
pAlcohoolDegreesControl->Show();
break;
default:
break;
}在对话框的确认过程(OnOK)上,在将值保存到相应的app var之前,我可以检查该值是否超出了边界:
int ix= pComboDrink->GetCurSel();
if (ix == -1)
return FALSE;
#pragma push_macro("min")
#undef min
#pragma push_macro("max")
#undef max
if (ix < static_cast<int> (std::numeric_limits<Drink>::min()) || ix > static_cast<int> (std::numeric_limits<Drink>::max()) )
return FALSE;
#pragma pop_macro("min")
#pragma pop_macro("max")
theApp.m_drink= static_cast<Drink>(ix);备注:
constexpr (我注释了/*expr*/,保留为const )和noexcept只是因为我正在使用的编译器(VisualC++ 2013)在当前版本中还不支持它们。default()不适合于“数字限制”范围;但是它似乎是一个很方便的地方来放置它;甚至它与default单词(在某些情况下是关键字)是一致的!发布于 2012-10-19 10:29:47
不,没有,如果您需要这个,您可能不应该首先使用enum。
在您的特定案例中,您希望调用Count的用例是什么?
发布于 2012-10-19 10:30:57
AFAIK没有自动编译器支持的关键字来获取enum中的元素总数。OTOH通常没有意义:您可能有多个具有相同值的值,只要这些值不必有相应的值(即您可以手动分配值,而不是依赖自动编号)。
一个常见的做法是以下列方式声明enum:
typedef enum
{
Stopped,
Playing,
Paused,
count
}PossibleValues; 这样,如果count总是最后定义的-它将给您枚举元素的计数,假设编号从0开始并是后续的。
发布于 2015-05-27 13:16:06
重新发布一个类似问题(非序整数c++枚举的最佳方法是什么?)的答案,因为它与一个几乎没有答案的问题有关。
用于获取所需内容的模式是使用std::initializer_list来存储枚举的所有值。
namespace PossibleValues
{
enum Type
{
ZERO= 0,
PLUS180= 180,
PLUS90= 90,
MINUS90= -90
};
constexpr auto Values = {ZERO, PLUS180, PLUS90, MINUS90};
size_t Count() { return Values.size(); }
Type Default() { return *begin(Values); }
}这还可以迭代枚举的值,即使它们没有线性值。
我认为你可以用一个不同的宏从一个宏生成枚举,初始化列表和函数,尽管在最好的情况下,这类事情应该在标准中。
编辑:当我使用PossibleValues作为枚举或对PossibleValues使用结构时,我的编译器会抱怨类型不完整。为枚举使用命名空间是有点不寻常的,但它工作得很好。
https://stackoverflow.com/questions/12972317
复制相似问题