Robert Gould
Robert Gould

Reputation: 69825

Is there a correct way to avoid warnings when comparing two different enums?

When comparing enums that come from different sources such as those of the following code GCC emits warnings. Is there a way to avoid these warnings without c-style casts?

struct Enumerator
{
    enum { VALUE = 5 };
};

template<int V>
struct TemplatedEnumerator
{
    enum { VALUE = V };
};

if(Enumerator::VALUE == TemplatedEnumerator<5>::VALUE)
{
  ...
}

And GCC emits the following type of warning:

GCC: warning: comparison between 'enum ...' and 'enum ...'

Upvotes: 6

Views: 5933

Answers (6)

Konrad Rudolph
Konrad Rudolph

Reputation: 545578

Simple answer in your case: don't use an enum, use an inline-defined static const int:

struct Enumerator
{
    static int const VALUE = 5;
};

template<int V>
struct TemplatedEnumerator
{
    static int const VALUE = V;
};

In this special case, that's equivalent and all compilers of the last few years should treat it so (I know for a fact that all the major ones do).

See also: static const Member Value vs. Member enum : Which Method is Better & Why?

Upvotes: 1

Eclipse
Eclipse

Reputation: 45493

I believe you can provide your own comparison operators, but you'll have to name the enums first:

struct Enumerator
{
    enum Values { VALUE = 5 };
};

template<int V>
struct TemplatedEnumerator
{
    enum Values { VALUE = V };
};


template <int V>
bool operator==(Enumerator::Values lhs, typename TemplatedEnumerator<V>::Values rhs)
{
    return static_cast<int>(lhs) == static_cast<int>(rhs);
}

template <int V>
bool operator==(typename TemplatedEnumerator<V>::Values rhs, Enumerator::Values lhs)
{
    return static_cast<int>(lhs) == static_cast<int>(rhs);
}

Interestingly Visual Studio doesn't actually warn about comparing the two enumerator types, but rather warns about a constant value in a if statement - just like it will if you do this:

if (true) {...}

Upvotes: 9

Stack Overflow is garbage
Stack Overflow is garbage

Reputation: 247929

You're missing the obvious answer. No, don't use c-style cast. Use C++-style casts:

if(static_cast<int>(Enumerator::VALUE) == static_cast<int>(TemplatedEnumerator<5>::VALUE))
{

}

Perfectly safe, perfectly acceptable. Two enums are not the same types, so if there's anything fishy in your code, it's not the cast, it's the attempt to compare two distinct types. But as long as you do it, a cast would be my preferred way to do it. Yes, you could define a comparison operator, but a cast makes it clear that you're comparing two technically unrelated types.

Upvotes: 0

starblue
starblue

Reputation: 56762

Don't do it.

The warning is there because you shouldn't mix up different enums in the first place.

For constants you can use a const declaration.

Upvotes: 2

ZaDDaZ
ZaDDaZ

Reputation: 131

If there are N enums, won't there need to be N * (N - 1) comparison operators? That could end up being a lot.

Couldn't you just use the implicit conversion of enums to ints and do:

bool equals(int lhs, int rhs)
{
  return lhs == rhs;
}

Then you can just do this in your code:

if(equals(Enumerator::VALUE, TemplatedEnumerator<5>::VALUE))
{
  ...
}

Also, you can check out enum-int casting: operator or function. The accepted answer says that you shouldn't use the implicit conversion, but a correctly named function like equals should make the code very readable and maintainable.

Upvotes: 2

Friedrich
Friedrich

Reputation: 5996

#include <iostream>
using namespace std;

struct Enumerator 
{
  enum {value = 5 };
};


template<int v>
struct TemplatedEnumerator
{ 
  enum {value = v};
};



int main(void)
{
  if (static_cast<int>(Enumerator::value) ==
    static_cast<int>(TemplatedEnumerator<5>::value))
    cout << "Yoh\n";
}

Upvotes: 1

Related Questions