您在 C++ 中使用哪种类型安全枚举? [英] Which Typesafe Enum in C++ Are You Using?

查看:25
本文介绍了您在 C++ 中使用哪种类型安全枚举?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

众所周知,C++ 中的内置枚举不是类型安全的.我想知道那里使用了哪些实现类型安全枚举的类......我自己使用以下自行车",但它有点冗长和有限:

It is common knowledge that built-in enums in C++ are not typesafe. I was wondering which classes implementing typesafe enums are used out there... I myself use the following "bicycle", but it is somewhat verbose and limited:

typesafeenum.h:

typesafeenum.h:

struct TypesafeEnum
{
// Construction:
public:
    TypesafeEnum(): id (next_id++), name("") {}
    TypesafeEnum(const std::string& n): id(next_id++), name(n) {}

// Operations:
public:
    bool operator == (const TypesafeEnum& right) const;
    bool operator != (const TypesafeEnum& right) const;
    bool operator < (const TypesafeEnum& right) const;

    std::string to_string() const { return name; }

// Implementation:
private:
    static int next_id;
    int id;
    std::string name;
};

typesafeenum.cpp:

typesafeenum.cpp:

int TypesafeEnum::next_id = 1;

bool TypesafeEnum::operator== (const TypesafeEnum& right) const 
{ return id == right.id; }

bool TypesafeEnum::operator!= (const TypesafeEnum& right) const 
{ return !operator== (right); }

bool TypesafeEnum::operator< (const TypesafeEnum& right) const  
{ return id < right.id; }

用法:

class Dialog 
{
 ...
    struct Result: public TypesafeEnum
    {
        static const Result CANCEL("Cancel");
        static const Result OK("Ok");
    };


    Result doModal();
 ...
};

const Dialog::Result Dialog::Result::OK;
const Dialog::Result Dialog::Result::CANCEL;

添加:我想我应该更具体地说明要求.我会试着总结一下:

Addition: I think I should have been more specific about the requirements. I'll try to summarize them:

优先级 1:将枚举变量设置为无效值应该是不可能的(编译时错误),没有例外.

Priority 1: Setting an enum variable to an invalid value should be impossible (a compile-time error) with no exceptions.

优先级 2:应该可以通过单个显式函数/方法调用将枚举值转换为 int 值.

Priority 2: Converting an enum value to/from an int should be possible with a single explicit function/method call.

优先级 3:尽可能简洁、优雅和方便的声明和使用

Priority 3: As compact, elegant and convenient declaration and usage as possible

优先级 4:将枚举值与字符串相互转换.

Priority 4: Converting enum values to and from strings.

优先级 5:(很高兴)可以迭代枚举值.

Priority 5: (Nice to have) Possibility to iterate over enum values.

推荐答案

我目前正在研究 Boost Vault(文件名 enum_rev4.6.zip).尽管它从未正式提交以包含在 Boost 中,但它可以按原样使用.(文档缺乏,但通过清晰的源代码和良好的测试来弥补.)

I'm currently playing around with the Boost.Enum proposal from the Boost Vault (filename enum_rev4.6.zip). Although it was never officially submitted for inclusion into Boost, it's useable as-is. (Documentation is lacking but is made up for by clear source code and good tests.)

Boost.Enum 允许你像这样声明一个枚举:

Boost.Enum lets you declare an enum like this:

BOOST_ENUM_VALUES(Level, const char*,
    (Abort)("unrecoverable problem")
    (Error)("recoverable problem")
    (Alert)("unexpected behavior")
    (Info) ("expected behavior")
    (Trace)("normal flow of execution")
    (Debug)("detailed object state listings")
)

并让它自动扩展为:

class Level : public boost::detail::enum_base<Level, string>
{
public:
    enum domain
    {
        Abort,
        Error,
        Alert,
        Info,
        Trace,
        Debug,
    };

    BOOST_STATIC_CONSTANT(index_type, size = 6);

    Level() {}
    Level(domain index) : boost::detail::enum_base<Level, string>(index) {}

    typedef boost::optional<Level> optional;
    static optional get_by_name(const char* str)
    {
        if(strcmp(str, "Abort") == 0) return optional(Abort);
        if(strcmp(str, "Error") == 0) return optional(Error);
        if(strcmp(str, "Alert") == 0) return optional(Alert);
        if(strcmp(str, "Info") == 0) return optional(Info);
        if(strcmp(str, "Trace") == 0) return optional(Trace);
        if(strcmp(str, "Debug") == 0) return optional(Debug);
        return optional();
    }

private:
    friend class boost::detail::enum_base<Level, string>;
    static const char* names(domain index)
    {
        switch(index)
        {
        case Abort: return "Abort";
        case Error: return "Error";
        case Alert: return "Alert";
        case Info: return "Info";
        case Trace: return "Trace";
        case Debug: return "Debug";
        default: return NULL;
        }
    }

    typedef boost::optional<value_type> optional_value;
    static optional_value values(domain index)
    {
        switch(index)
        {
        case Abort: return optional_value("unrecoverable problem");
        case Error: return optional_value("recoverable problem");
        case Alert: return optional_value("unexpected behavior");
        case Info: return optional_value("expected behavior");
        case Trace: return optional_value("normal flow of execution");
        case Debug: return optional_value("detailed object state listings");
        default: return optional_value();
        }
    }
};

它满足您列出的所有五个优先事项.

It satisfies all five of the priorities which you list.

这篇关于您在 C++ 中使用哪种类型安全枚举?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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