Reputation: 69825
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
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
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
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
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
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
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