C ++中哪些类型安全枚举是使用的? [英] Which Typesafe Enum in C++ Are You Using?

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

问题描述

常见的知识是C ++中内置的枚举不是类型安全的。
我想知道哪些类实现类型安全枚举在那里使用
我自己使用以下自行车,但它有点冗长和限制:



typesafeenum.h:

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

//操作:
public:
bool operator ==(const TypesafeEnum& right)const;
bool operator!=(const TypesafeEnum& right)const;
bool运算符< (const TypesafeEnum& right)const;

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

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

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结果:public TypesafeEnum
{
static const Result CANCEL(Cancel);
static const Result OK(Ok);
};


结果doModal();
...
};

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

添加:
我认为我应该更具体关于要求。我将尝试总结一下:



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

优先级2:使用单个显式函数/方法调用,可以将枚举值转换为/从int转换。



<优先级3:尽可能小巧优雅,方便的申报和使用



优先级4:将枚举值转换为字符串和/或从字符串转换。



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

解决方案

目前正在使用 Boost Vault (文件名)中的Boost.Enum提案enum_rev4.6.zip )。虽然它从未正式提交包含在Boost中,但可以按原样使用。 (文档不足,但是通过清晰的源代码和良好的测试来弥补)。



Boost.Enum可以让你声明这样的枚举:

  BOOST_ENUM_VALUES(级别,const char *,
(中止)(不可恢复的问题)
(错误)(可恢复问题
(警报)(意外行为)
(信息)(预期行为)
(跟踪)(正常执行流程)
(调试) (详细对象状态列表)

并将其自动扩展为:

  class Level:public boost :: detail :: enum_base< Level,string> 
{
public:
枚举域
{
中止,
错误,
提醒,
信息,
跟踪,
调试,
};

BOOST_STATIC_CONSTANT(index_type,size = 6);

级别(){}
级别(域索引):boost :: detail :: enum_base<级别,字符串>(索引){}

typedef boost ::可选<平>可选的;
static可选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 * name(domain index)
{
switch(index)
{
case Abort:returnAbort;
case错误:returnError;
病警告:返回警报;
case信息:returnInfo;
case跟踪:returnTrace;
case Debug:returnDebug;
default:return NULL;
}
}

typedef boost :: optional< value_type> optional_value;
static optional_value values(domain index)
{
switch(index)
{
case中止:return optional_value(unrecoverable problem);
case错误:return optional_value(可恢复问题);
case Alert:return optional_value(unexpected behavior);
case信息:return optional_value(expected behavior);
case跟踪:return optional_value(正常执行流程);
case Debug:return optional_value(详细的对象状态列表);
default:return optional_value();
}
}
};

它满足您列出的所有五个优先级。


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:

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:

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; }

Usage:

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:

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

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

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

Priority 4: Converting enum values to and from strings.

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

解决方案

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 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")
)

And have it automatically expand to this:

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天全站免登陆