计数枚举C ++自动 [英] Count on enum C++ automatic

查看:232
本文介绍了计数枚举C ++自动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用C ++编写枚举时遇到了一个模式。它是这样的:

I've come to a pattern when writing enums in C++. It is like this:

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()是手动完成。只有两种方式我知道如何做:这一个是从最后+ 1计算;或者写简单的硬编码。

This solves a some of the usual issues with enums, like pollution of outside namespaces, etc. But there is still a thing I don't like: The Count() is done manually. There are only two ways I know how to do it: this one is calculated from Last+1; or write plain hardcoded.

问题是:有一些方法,像使用预处理器宏,自动获取计数,放在Count()方法后?注意:我不想在枚举中有一个最后一个假的元素Count,污染它!

Question is: Is there some way, like using preprocessor macros, that automatically gets the count, to put it after in the Count() method? Attention: I don't want to have a last fake element called Count inside the enum, polluting it!

提前感谢!

更新1:

有关在标准C ++ 11(部分)中实现N4428枚举反射枚举。

There is an interesting discussion on Implementation of N4428 enum reflection in standard C++11 (partial) for a proposal of more advanced enums.

更新2:

有趣的文档 N4451-静态反射(第3版)在其部分3.16 ,3.17,A.7,A.8关于MetaEnums和MetaEnumClasses。

Interesting document N4451- Static reflection (rev. 3) on its sections 3.16, 3.17, A.7, A.8 about MetaEnums and MetaEnumClasses.

更新3:

我来到另一个有趣的模式使用枚举类,在我看到 https://bytes.com/topic/c/answers/127908-numeric_limits-specialization#post444962 。如果枚举类的枚举列表是连续整数,通过定义其最大值和最小值,我们可以检查值是否属于它。

I came to another interesting pattern using an enum class, after I've seen https://bytes.com/topic/c/answers/127908-numeric_limits-specialization#post444962. If the enum class's enumerator list is continuously integer, by defining its maximum and its minimum, we can check whether a value belongs to it or not.

如果在 Player :: State上使用 Count() 是检查一个值是否在枚举中,该目的也已通过numeric_limits方法实现,并且甚至更好,因为它不需要枚举器列表以零值项开始! / p>

If the purpose of using the Count() method on the Player::State was to check if a value was in the enum, that purpose has also been achieved with the numeric_limits approach, and is even superior, as it is not required the enumerator list begins with a ZERO valued item!

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;

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

which in constructor is initialized with:

m_drink = numeric_limits<Drink>::default();

在初始化表单时,我可以:

On the initialization of a form, I can do:

pComboDrink->SetCurSel(static_cast<int>(theApp.m_drink));

在此界面上,为了使界面适应用户所做的更改,我可以使用scoped枚举类值:

On it, for adapting the interface to changes done by the user, I can do a switch with scoped enum class values:

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 ),我可以检查该值是否超出边界,然后保存到相应的应用程序var:

And on the dialog's confirmation procedure (OnOK), I can check if the value is out of boundaries, before saving it to the respective 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);

注意:


  1. 关键字 constexpr (我评论了 / * expr * / ,将其保留为因为我使用的编译器(Visual C ++ 2013)在当前版本还不支持它们,所以注释掉 )和 noexcept

  2. 我知道 default()

  3. 也许你不需要逻辑来暂时定义最小和最大宏。 / code>不适合在数字限制范围;但它似乎是一个方便的地方,它把它;即使它与在某些上下文中是

  1. The keywords constexpr (I commented /*expr*/, leaving it as const ) and noexcept are commented only because the compiler I am using (Visual C++ 2013) does not support them yet at the current version.
  2. Maybe you do not need the logic to temporary undefine the min and max macros.
  3. I know that the default() does not fit on a "numeric limits" scope; but it seemed an handy place to put it on; even it coincides with the default word that in some contexts is a keyword!


推荐答案

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

AFAIK there's no automatic compiler-supported keyword to get the total amount of elements in enum. OTOH this usually doesn't make sense: you may have multiple values with the same value, as long as the values don't have to have consequent values (i.e. you may assign the values manually, rather than rely on automatic numbering).

一种常见做法是以下列方式声明枚举

One common practice is to declare the enum in the following way:

  typedef enum
    {
        Stopped, 
        Playing, 
        Paused,

        count

    }PossibleValues;  

这样,如果 count last - 它将给你枚举元素的数量,假设编号从0开始并且是后果。

This way, if count is always defined last - it will give you the count of the enum elements, assuming the numbering starts from 0 and is consequent.

这篇关于计数枚举C ++自动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆