3

This code:

enum : unsigned { foo = 4 };
enum : unsigned { bar = 32 };

int main() { return bar > foo; }

gives me the following warning (with GCC 5.4.0):

$ g++ --std=c++11 -o a a.cpp
a.cpp: In function ‘int main()’:
a.cpp:4:27: warning: comparison between ‘enum<anonymous>’ and ‘enum<anonymous>’ [-Wenum-compare]
 int main() { return bar > foo; }
                     ^

Why is that? I've specified exactly which types these enum values have, there's nothing indeterminate about comparing them. I've even used the same type for both enums (not that it should matter). So what's the deal here?

Note that clang (3.8.0) doesn't produce this warning, even with -Wall.

einpoklum
  • 118,144
  • 57
  • 340
  • 684
  • 2
    You're comparing apples to oranges.You're free to turn off or ignore the warning. It's hard to imagine circumstances in which this would be legitimate, but if you know it's sensible, then you can cast one side to the type of the other or cast both sides to a common type. If it's a measurable thing, why use an `enum` over an `unsigned`? And if it's not measurable, why compare it? And why compare different immeasurable units? – David Schwartz Apr 24 '17 at 19:46
  • @DavidSchwartz: Not really so hard to [imagine](http://stackoverflow.com/questions/22867654/enum-vs-constexpr-for-actual-static-constants-inside-classes?s=8|1.5237), actually. – einpoklum Apr 24 '17 at 19:50

1 Answers1

2

Why is that? I've specified exactly which types these enum values have, there's nothing indeterminate about comparing them. I've even used the same type for both enums (not that it should matter). So what's the deal here?

The warning doesn't say anything about indeterminate, it tells you that you're comparing distinct types. If the values are represented by different types then it suggests they mean different things, and so comparing them might be questionable. As David said, comparing N apples to M oranges is odd and deserves a warning.

The underlying type doesn't change anything, because foo is not an unsigned, and bar is not an unsigned. If you wanted to compare unsigned values then the compiler assumes you'd be using unsigned and not enumeration types.

From your comment on the other answer:

Because I use enums for constants in (different) classes - things like limits and sizes.

Why? What's wrong with using constexpr static data members for that?

This is covered in the C++ Core Guidelines, see Avoid unnamed enumerations:

Such code is not uncommon in code written before there were convenient alternative ways of specifying integer constants.

Alternative: Use constexpr values instead.

Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521
  • "What's wrong with using constexpr etc.?" Ah! I've just [asked](http://stackoverflow.com/questions/43595668/which-should-i-prefer-for-a-constant-within-a-function-constexpr-const-or-enum) about that myself and I have an [answer](http://stackoverflow.com/a/43597564/1593077) too. – einpoklum Apr 24 '17 at 20:58
  • Also, you wrote the comparison "might be questionable". I suppose that could be true sometimes - but the comparison is not _inherently_ questionable. Comparing a `uint32_t` to a `uint16_t` can also be questionable in some cases (e.g. you might forget the RHS is smaller and try to increase it up to the LHS which is set at 2^16). Or using the result of a logical operation in integer arithmetic; that's often useful but it could very well be the result of a novice programmer's forgetting to use parentheses (`5 + 5 > 9`). But you wouldn't give me a warning about that kind of code, right? – einpoklum Apr 24 '17 at 21:02