首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >枚举C++自动计数

枚举C++自动计数
EN

Stack Overflow用户
提问于 2012-10-19 10:26:59
回答 5查看 12.2K关注 0票数 3

在用C++编写枚举时,我发现了一种模式。它是这样的:

代码语言:javascript
复制
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方法实现的,甚至更优越,因为它不需要枚举器列表以零值项开始!

代码语言:javascript
复制
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")

使用情况:

应用程序中的一个变量:

代码语言:javascript
复制
Drink m_drink;

在构造函数中,其初始化为:

代码语言:javascript
复制
m_drink = numeric_limits<Drink>::default();

对于表单的初始化,我可以这样做:

代码语言:javascript
复制
pComboDrink->SetCurSel(static_cast<int>(theApp.m_drink));

在它上,为了使界面适应用户所做的更改,我可以使用限定作用域的枚举类值进行切换:

代码语言:javascript
复制
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之前,我可以检查该值是否超出了边界:

代码语言:javascript
复制
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);

备注:

  1. 关键字constexpr (我注释了/*expr*/,保留为const )和noexcept只是因为我正在使用的编译器(VisualC++ 2013)在当前版本中还不支持它们。
  2. 也许您不需要逻辑来暂时取消对min和max宏的定义。
  3. 我知道default()不适合于“数字限制”范围;但是它似乎是一个很方便的地方来放置它;甚至它与default单词(在某些情况下是关键字)是一致的!
EN

回答 5

Stack Overflow用户

发布于 2012-10-19 10:29:47

不,没有,如果您需要这个,您可能不应该首先使用enum

在您的特定案例中,您希望调用Count的用例是什么?

票数 3
EN

Stack Overflow用户

发布于 2012-10-19 10:30:57

AFAIK没有自动编译器支持的关键字来获取enum中的元素总数。OTOH通常没有意义:您可能有多个具有相同值的值,只要这些值不必有相应的值(即您可以手动分配值,而不是依赖自动编号)。

一个常见的做法是以下列方式声明enum

代码语言:javascript
复制
  typedef enum
    {
        Stopped, 
        Playing, 
        Paused,

        count

    }PossibleValues;  

这样,如果count总是最后定义的-它将给您枚举元素的计数,假设编号从0开始并是后续的。

票数 3
EN

Stack Overflow用户

发布于 2015-05-27 13:16:06

重新发布一个类似问题(非序整数c++枚举的最佳方法是什么?)的答案,因为它与一个几乎没有答案的问题有关。

用于获取所需内容的模式是使用std::initializer_list来存储枚举的所有值。

代码语言:javascript
复制
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使用结构时,我的编译器会抱怨类型不完整。为枚举使用命名空间是有点不寻常的,但它工作得很好。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12972317

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档