强类型枚举中出现负值的Clang Comparison Bug



我最近处理了使用包含负值的强类型枚举的代码。当比较枚举的值时,我在用Clang(3.3)编译代码时得到了奇怪的结果,而Gcc运行得很好。

下面是一个断言失败的小例子。

enum class T: int { A = -1, B = 1 };
int main() {
    T a = T::A, b = T::B;
    assert(a < b);
}

这是一个真正的bug吗?或者clang的行为是否正确,而gcc只是提供了某种遗留支持?

应该更直观的是,以下是格式良好的

T a = T::A;
assert(a == T::A);

但是相等运算符(==!=)与关系运算符(<<=,..)具有相同的限制[expr.eq]/1:

==(等于)和!=(不等于)运算符具有与关系运算符相同的语义限制、转换和结果类型,只是它们的优先级和真值结果较低。

因此,如果定义了作用域枚举类型的值之间的相等性,那么<也应该是.


[expr.rel]/1

操作数应具有算术、枚举或指针类型,或类型std::nullptr_t

当然,通常的算术转换是对算术或枚举类型[expr.rel]/2的操作数执行的,其中转换是作用域枚举的身份转换(没有积分提升,请参见[expr]/10第一个项目符号)。然而,[expr.rel]/5明确指出:

如果两个操作数(转换后的)都是算术或枚举类型,则每个操作数应产生如果指定的关系为真则为true,如果为假则为false

(重点矿井)

因此,T::A < T::B应形成良好的产生true


正如我在评论中所写的,clang++3.4 trunk 193040上的断言没有失败。因此,我认为这是一个已经修复的错误,尽管我找不到相应的错误报告。

最新更新