C++ “背后的推理”;“条件表达式中的枚举和非枚举类型”;

C++ “背后的推理”;“条件表达式中的枚举和非枚举类型”;,c++,c++11,coding-style,C++,C++11,Coding Style,由于C++11转换,GCC输出一个警告“条件表达式中的枚举和非枚举类型”。我想了解这一警告背后的原因。比较枚举常量有什么危险 很明显,我们可以通过 -Wno枚举比较 通过显式转换为整型 但为什么要这么麻烦呢?就我个人而言,我一直致力于编写无警告代码,通常默认情况下发出的警告是相当合理的。例如,它认为比较有符号整数和无符号整数是危险的 但是使用枚举是习惯用法C++的元编程。我不知道有任何替代方案,同样可读、简洁、切中要害,并且不需要任何实际存储 举一个具体的例子:下面的元函数会出什么问题,这样

由于C++11转换,GCC输出一个警告“条件表达式中的枚举和非枚举类型”。我想了解这一警告背后的原因。比较枚举常量有什么危险

很明显,我们可以通过

  • -Wno枚举比较
  • 通过显式转换为整型
但为什么要这么麻烦呢?就我个人而言,我一直致力于编写无警告代码,通常默认情况下发出的警告是相当合理的。例如,它认为比较有符号整数和无符号整数是危险的

<>但是使用枚举是习惯用法C++的元编程。我不知道有任何替代方案,同样可读、简洁、切中要害,并且不需要任何实际存储

举一个具体的例子:下面的元函数会出什么问题,这样警告就足够了

template<class TYPES>
struct MaxSize;
template<>
struct MaxSize<NullType>
  {
    enum{ value = 0 };
  };
template<class TY, class TYPES>
struct MaxSize<Node<TY,TYPES> >
  {
    enum{ thisval = sizeof(TY)
        , nextval = MaxSize<TYPES>::value
        , value   = nextval > thisval?  nextval:thisval
        };
  };
模板
结构最大尺寸;
模板
结构最大尺寸
{
枚举{value=0};
};
模板
结构最大尺寸
{
枚举{thisval=sizeof(TY)
,nextval=MaxSize::value
,value=nextval>thisval?nextval:thisval
};
};

如果使用枚举作为定义编译时常量值的方法,现在可以停止这样做

改用这个:

constexpr int myConstant = 123;
其中
int
可以是任何符合
literal类型的内容
[我不会在这里尝试定义literal类型——这很复杂,谷歌是你的朋友。]

或者,甚至在c++11之前,您也可以说:

class Foo{
    static const int myConstant = 123;
 };
其中int可以是任何整数类型

除非您需要myConstant的地址,否则cpp文件中不需要相应的定义


编译器告诉您,将枚举值与同一枚举中的其他值进行比较是脆弱的代码。

这在GCC中似乎是个问题。这不依赖于
-std=c++11
选项。警告与比较无关,而是与条件运算符有关

似乎只有当其中一个枚举成员使用无符号值初始化,而另一个成员使用另一个枚举的值初始化时,才会发出警告。此外,该警告仅在初始化枚举成员时发出

我设法将代码精简为以下内容:

enum A { valueA = 1 };

enum B { 
    // if you change 0u to 0, there'll be no warning
    thisval = 0u, 
    // if you change valueA to any integral constant, there'll be no warning
    nextval = valueA, 
    // warning on this line
    value = nextval > thisval ? nextval : thisval,
    // no warning here
    value2 = nextval > thisval
};

int main() {
    // no warning here
    (void)(nextval > thisval ? nextval : thisval);
    // the same warning also here - but not with Clang
    (void)(nextval > thisval ? nextval : false);
}

Clang没有对此代码发出任何警告(除了使用
-Weverything
时,它会抱怨无法访问代码),尽管它确实可以在最后一行说些什么


(GCC 4.9.2,Clang 3.5.0)

当您意外地将其绑定到常量引用时,
静态常量
方法可能会导致意外,这需要一个定义。@T.C.:因此在我的回答中,“除非您需要地址…”。是的,问题是它的发生频率可能比预期的要高,对于实际用例,
static constexpr size\u t something=..
看起来像是枚举常量的替换。当然,没有为静态常量实际分配存储。我不认为这是一种风格上的改进。它用没有附加信息值的冗长表示法替换了一个简短的表示法,并且用一个从未分配的声明常量完成了一个技巧,依靠编译器来解决问题。此外,我仍然看不到编译器警告的危险。在引用的示例中,我们只比较同一枚举中的常量,而不是有符号与无符号的比较。正如安东·萨文(Anton Savin)在其回答中指出的那样,GCC的警告在这种情况下实际上可能是错误的和不合理的。在您发布的代码中,唯一的比较是
nextval>thisval
。它们都是枚举值。我不明白为什么编译器会抱怨。