你能实现标准的符合性(如n3242草案17.5.2.1.3描述)使用枚举类类型安全的位掩码? 我读的方式,类型T是位掩码,如果它支持|,&,^,〜,| =,&=和^ =运营商,并进一步可以做,如果(L&R),其中L和R是T型的从列表中缺少的操作!=和==,并允许一个排序大概也想超载<。
获取运营商的作品是只是恼人的样板代码,但我不知道怎样做,如果(L&R)。 至少以下不与GCC编译(除了是极其危险的,因为它允许一个错误的隐式转换为int):
enum class Foo{
operator bool(){
return (unsigned)*this;
}
};
编辑:我现在肯定知道枚举类不能有成员。 实际的问题,如果(L&R)如何做仍虽然。
我认为你可以......你必须添加运营商bitmasky事情。 真的不是我在这里,但你可以很容易地重载任何关系运算符。
/**
*
*/
// NOTE: I changed to a more descriptive and consistent name
// This needs to be a real bitmask type.
enum class file_permissions : int
{
no_perms = 0,
owner_read = 0400,
owner_write = 0200,
owner_exe = 0100,
owner_all = 0700,
group_read = 040,
group_write = 020,
group_exe = 010,
group_all = 070,
others_read = 04,
others_write = 02,
others_exe = 01,
others_all = 07,
all_all = owner_all | group_all | others_all, // 0777
set_uid_on_exe = 04000,
set_gid_on_exe = 02000,
sticky_bit = 01000,
perms_mask = all_all | set_uid_on_exe | set_gid_on_exe | sticky_bit, // 07777
perms_not_known = 0xffff,
add_perms = 0x1000,
remove_perms = 0x2000,
symlink_perms = 0x4000
};
inline constexpr file_permissions
operator&(file_permissions x, file_permissions y)
{
return static_cast<file_permissions>
(static_cast<int>(x) & static_cast<int>(y));
}
inline constexpr file_permissions
operator|(file_permissions x, file_permissions y)
{
return static_cast<file_permissions>
(static_cast<int>(x) | static_cast<int>(y));
}
inline constexpr file_permissions
operator^(file_permissions x, file_permissions y)
{
return static_cast<file_permissions>
(static_cast<int>(x) ^ static_cast<int>(y));
}
inline constexpr file_permissions
operator~(file_permissions x)
{
return static_cast<file_permissions>(~static_cast<int>(x));
}
inline file_permissions &
operator&=(file_permissions & x, file_permissions y)
{
x = x & y;
return x;
}
inline file_permissions &
operator|=(file_permissions & x, file_permissions y)
{
x = x | y;
return x;
}
inline file_permissions &
operator^=(file_permissions & x, file_permissions y)
{
x = x ^ y;
return x;
}
我不能完全确定你的验收标准是什么,但你可以只是使operator &
返回用适当的转换和包装类explicit operator bool
:
#include <type_traits>
template<typename T> using Underlying = typename std::underlying_type<T>::type;
template<typename T> constexpr Underlying<T>
underlying(T t) { return Underlying<T>(t); }
template<typename T> struct TruthValue {
T t;
constexpr TruthValue(T t): t(t) { }
constexpr operator T() const { return t; }
constexpr explicit operator bool() const { return underlying(t); }
};
enum class Color { RED = 0xff0000, GREEN = 0x00ff00, BLUE = 0x0000ff };
constexpr TruthValue<Color>
operator&(Color l, Color r) { return Color(underlying(l) & underlying(r)); }
您的所有其他运营商可以继续返回Color
,当然:
constexpr Color
operator|(Color l, Color r) { return Color(underlying(l) | underlying(r)); }
constexpr Color operator~(Color c) { return Color(~underlying(c)); }
int main() {
constexpr Color YELLOW = Color::RED | Color::GREEN;
constexpr Color WHITE = Color::RED | Color::GREEN | Color::BLUE;
static_assert(YELLOW == (WHITE & ~Color::BLUE), "color subtraction");
return (YELLOW & Color::BLUE) ? 1 : 0;
}
作用域枚举(那些具有任一创建enum class
或enum struct
)不类。 他们不能有成员函数,他们只是提供封闭式统计员(在命名空间级别不可见)。
从列表中缺少的是操作!=和==
这些运营商正在通过枚举类型,整数类型和已支持std::bitset
,所以没有必要重载它们。
并允许重新排列一个大概也想超载<。
你为什么要位掩码排序? 是(A | B)大于(A | C)? 是std::ios::in
小于std::ios::app
? 有关系吗? 关系运算符总是为枚举类型和整数类型定义的反正。
要回答的主要问题,你将实现&
作为一个重载的非成员函数:
Foo operator&(Foo l, Foo r)
{
typedef std::underlying_type<Foo>::type ut;
return static_cast<Foo>(static_cast<ut>(l) & static_cast<ut>(r));
}
我相信所有的位掩码类型所需的操作可以为范围的枚举定义,但不要求如
词和CJ是非零和C&CJ iszero
和:
Y在处理对象物X中设置的值是表达式X和Y是非零。
由于范围的枚举不支持impicit转换为整数类型,你不能可靠地测试,如果是非零与否。 你需要写if ((X&Y) != bitmask{})
我不认为这是该委员会的意图。
(我最初以为他们可以用来定义位掩码类型,才想起我会尝试使用范围的枚举实现一个和遇到的测试问题的零/非零。)
编辑:我刚刚想起std::launch
是一个范围的枚举类型和掩码类型...所以显然作用域枚举可以位掩码类型!
下面枚举标志简单例子。
#indlude "enum_flags.h"
ENUM_FLAGS(foo_t)
enum class foo_t
{
none = 0x00
,a = 0x01
,b = 0x02
};
ENUM_FLAGS(foo2_t)
enum class foo2_t
{
none = 0x00
,d = 0x01
,e = 0x02
};
int _tmain(int argc, _TCHAR* argv[])
{
if(flags(foo_t::a & foo_t::b)) {};
// if(flags(foo2_t::d & foo_t::b)) {}; // Type safety test - won't compile if uncomment
};
ENUM_FLAGS(T)是一个宏,在定义enum_flags.h (小于100行,自由没有任何限制使用)。