我最近使用包含负值的强类型枚举来处理代码。 当比较枚举的值时,在使用Clang(3.3)编译代码时,我得到了奇怪的结果,而Gcc的工作正常。
这是一个断言失败的小例子。
enum class T: int { A = -1, B = 1 };
int main() {
T a = T::A, b = T::B;
assert(a < b);
}
这是一个真正的错误吗?或者clang行为正确,gcc只提供某种遗留支持吗?
答案 0 :(得分:0)
以下格式良好:
应该更加直观T a = T::A;
assert(a == T::A);
但是相等运算符(==
,!=
)与关系运算符(<
,<=
,..)[expr.eq] /具有相同的限制1:
==
(等于)和!=
(不等于)运算符与关系运算符具有相同的语义限制,转换和结果类型,除了它们的优先级和真值之外结果
因此,如果范围明确的枚举类型的值之间的相等性是明确定义的,那么<
也应如此。
[expr.rel] / 1
操作数应具有算术,枚举或指针类型,或者键入
std::nullptr_t
。
当然,通常的算术转换是在算术或枚举类型[expr.rel] / 2的操作数上执行的,其中转换是作用域枚举的标识转换(没有整数提升,请参见[expr] / 10 first bullet )。但是,[expr.rel] / 5明确指出:
如果两个操作数(转换后 )都是算术类型或枚举类型,则每个操作符都应该产生 如果指定的关系为真,则
true
;如果指定的关系为假,则false
。
(强调我的)
因此,T::A < T::B
应该是格式正确的和收益true
。
正如我在评论中写的那样,断言在clang ++ 3.4 trunk 193040上没有失败。因此,我认为这是一个已修复的错误,即使我找不到相应的错误报告。