我有一些通用代码适用于使用C++ 11 enum class类型指定的标志.一步,我想知道标志中是否设置了任何位.目前,我正在使用代码:
if (flags != static_cast<E>(0)) // Works, but ugly.
Run Code Online (Sandbox Code Playgroud)
我还可以强制用户为全零字段指定一个特定的名称,这个名称更具可读性,但对使用它的任何人强加了我的命名约定:
if (flags != E::none) // Works, if you manually define none = 0.
Run Code Online (Sandbox Code Playgroud)
但这些都不像传统的那样好看:
if (flags) // Doesn't work with class enums.
Run Code Online (Sandbox Code Playgroud)
是否可以指定自定义函数来评估布尔上下文中的类枚举?
Joh*_*itb 28
就像@RMatin说的那样.但你可能超载operator!
bool operator!(E e) {
return e == static_cast<E>(0);
}
Run Code Online (Sandbox Code Playgroud)
这样你就可以使用这个!!e成语
if(!!e) {
...
}
Run Code Online (Sandbox Code Playgroud)
Pot*_*ter 19
是否可以指定自定义函数来评估布尔上下文中的类枚举?
是的,但不是自动的.手动调用函数仍然比其他替代方案更优雅.
只需选择一个不错的函数名称,例如any,并实现它.重载分辨率将确保您的功能与其他所有功能一起使用.
bool any( E arg )
{ return arg != E::none; }
...
if ( any( flags ) ) {
...
Run Code Online (Sandbox Code Playgroud)
看起来对我很好.
更新:如果您希望将其应用于多种枚举类型,则可以模板化:
template< typename enum_type > // Declare traits type
struct enum_traits {}; // Don't need to declare all possible traits
template<>
struct enum_traits< E > { // Specify traits for "E"
static constexpr bool has_any = true; // Only need to specify true traits
};
template< typename enum_type > // SFINAE makes function contingent on trait
typename std::enable_if< enum_traits< enum_type >::has_any,
bool >::type
any( enum_type e )
{ return e != enum_type::none; }
Run Code Online (Sandbox Code Playgroud)
我一直在使用这种机制来做其他事情,从未遇到任何副作用或问题:v).
您可以跳过该特征并将SFINAE条件设置为类似enum_type::none == enum_type::none,仅仅检查是否存在none等式运算符,但这样做不那么明确和安全.
如果你有一个标志字段(即:一个位域),我强烈建议你不要使用enum class位域.
强类型的枚举存在,强类型.它使枚举器不仅仅是常规枚举的命名常量整数.这个想法是,如果你有一个enum class类型的变量,那么它的内容应该始终与其中一个枚举器值完全匹配.这就是没有从整数类型到整数类型的隐式转换的原因.
但这不是你正在做的事情.你正在采用一个位域,这是一个枚举值的组合.那个构成本身并不是这些价值观中的任何一个; 这是他们的组合.因此,当你说你正在采取这种类型时,你撒谎enum class ; 你真的只是采用一个可能是enum class枚举器之一的无符号整数.
例如:
enum class Foo
{
First = 0x01,
Second = 0x02,
Third = 0x04,
};
Foo val = Foo::First | Foo::Second;
Run Code Online (Sandbox Code Playgroud)
val在这种情况下,不包含First,Second或Third.您丢失了强类型,因为它不包含任何类型.
enum class值不能隐式转换为bool; 它们不能隐式转换为整数; 并且它们不能隐含地对它们执行大多数数学运算.它们是不透明的值.
因此它们不适合用作位域.试图以enum class这种不恰当的方式使用只会导致大量的铸造.只要使用普通的老人enum,就可以省去痛苦.
struct Error {
enum {
None = 0,
Error1 = 1,
Error2 = 2,
} Value;
/* implicit */ Error(decltype(Value) value) : Value(value) {}
explicit operator bool() {
return Value != Error::None;
}
};
inline bool operator==(Error a, Error b) {
return a.Value == b.Value;
}
inline bool operator!=(Error a, Error b) {
return !(a == b);
}
Run Code Online (Sandbox Code Playgroud)
enum现在没有重载运算符,所以将它包装在class或中struct.
| 归档时间: |
|
| 查看次数: |
12651 次 |
| 最近记录: |