C ++中哪些类型安全枚举是使用的? [英] Which Typesafe Enum in C++ Are You Using?
问题描述
我想知道哪些类实现类型安全枚举在那里使用
我自己使用以下自行车,但它有点冗长和限制:
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屋!