10

Is there a way to make enum type to be unsigned? The following code gives me a warning about signed/unsigned comparison.

enum EEE {
    X1 = 1
};

int main()
{
    size_t x = 2;
    EEE t = X1;
    if ( t < x ) std::cout << "ok" << std::endl;

    return 0;
}

I've tried to force compiler to use unsigned underlying type for enum with the following:

enum EEE {
    X1 = 1,
    XN = 18446744073709551615LL
    // I've tried XN = UINT_MAX (in Visual Studio). Same warning.
};

But that still gives the warning.


Changing constant to UINT_MAX makes it working in GNU C++ as should be according to the standard. Seems to be a bug in VS. Thanks to James for hint.

Kirill V. Lyadvinsky
  • 97,037
  • 24
  • 136
  • 212
  • Related, but not duplicate: http://stackoverflow.com/questions/2579230/signedness-of-enum-in-c-c99-c-cx-gnu-c-gnu-c99 – James McNellis Apr 28 '10 at 18:19
  • http://stackoverflow.com/questions/159034/ – sbi Apr 28 '10 at 18:20
  • 2
    @sbi, that's not a duplicate, because C++ Standard gives a hint on how to change undelying type to unsigned int. And I'm trying to use that. – Kirill V. Lyadvinsky Apr 28 '10 at 18:24
  • 1
    @Sbi, next time, please copy and paste the *entire* URL. Stack Overflow will abbreviate it to what you posted anyway, but when you include the whole thing, we can get a tool tip showing the question title (actually, the remainder of the URL) without having to visit the link. Compare yours with James's comment. – Rob Kennedy Apr 28 '10 at 21:27
  • @Rob: You're right, it would have been better in this case. I got into the habit of snipping the redundant parts because the room for comments is limited. – sbi Apr 29 '10 at 05:19

6 Answers6

8

You might try:

enum EEE {
    X1 = 1,
    XN = -1ULL
};

Without the U, the integer literal is signed.

(This of course assumes your implementation supports long long; I assume it does since the original question uses LL; otherwise, you can use UL for a long).

James McNellis
  • 348,265
  • 75
  • 913
  • 977
  • 1
    This works in GNU C++, but not in Visual Studio. Seems to be a bug in VS. This code is correct also, but better to use `UINT_MAX`. – Kirill V. Lyadvinsky Apr 28 '10 at 18:44
  • @James, Ah, indeed. If you do it with "LLU" instead of just with "U" like i did, it can't choose "long" anymore. Good way to get around the unclear wording of what "larger" means! I would upvote if you use a limit macro or `-1ULL` (or `-1UL` in C++03 or long long implementation) :) – Johannes Schaub - litb Apr 28 '10 at 18:47
  • `ULLONG_MAX` doesn't work in VC++ also. I think compiler thinks he can generate 128bit code. – Kirill V. Lyadvinsky Apr 28 '10 at 18:59
  • 1
    @Johannes: Thanks for reminding me about the -1 trick; it had slipped my mind. – James McNellis Apr 28 '10 at 19:06
  • 1
    @Kirill: No matter what value I give an enumerator, the enumeration always has a size of four bytes in VS2008. :-/ – James McNellis Apr 28 '10 at 19:49
2

Not in the current version of C++. C++0x will provide strongly typed enums.

For the time being, you can use if ( static_cast<size_t>(t) < x ) to remove the warning.

In silico
  • 51,091
  • 10
  • 150
  • 143
2

You could also overload the operators if you want to compare it

enum EEE {
    X1 = 1
};

bool operator<(EEE e, std::size_t u) {
  return (int)e < (int)u;
}

However you have to do that dance for any integer type on the right side. Otherwise if you do e < 2 it would be ambiguous: The compiler could use your operator< matching the left side exactly but needing a conversion on the right side, or its built-in operator, needing a promotion for the left side and matching the rigth side exactly.

So ultimately, i would put the following versions:

/* everything "shorter" than "int" uses either int or unsigned */
bool operator<(EEE e, int u) {
  return (int)e < (int)u;
}

bool operator<(EEE e, unsigned u) {
  return (unsigned int)e < (unsigned int)u;
}


bool operator<(EEE e, long u) {
  return (long)e < (long)u;
}

bool operator<(EEE e, unsigned long u) {
  return (unsigned long)e < (unsigned long)u;
}

/* long long if your compiler has it, too */

Not very nice :) But at least the user of your enumeration has easy going. However if you ultimately don't want to compare against ordinary int but against some meaningful value, i would do what some other guy proposed, and add another enumerator that has as value 2, and name it. That way, warnings will go away too.

Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
  • Rather verbose, but gets the job done if you are looking to avoid static_cast – Ramon Zarazua B. Apr 28 '10 at 18:44
  • `-1U`? are you trying to apply an unary minus operator to unsigned type? Should that change the type to signed? – Kirill V. Lyadvinsky Apr 28 '10 at 18:48
  • @Kirill, it will stay `unsigned` but will change its value to `UINT_MAX`. So you don't need the limits header. – Johannes Schaub - litb Apr 28 '10 at 18:54
  • I removed the "trick" with the `UINT_MAX` because i think "larger" means actually the "sizeof" value - as in "size of the type" (after asking dgregor). "long" could be the same size of "unsigned int" and so it could choose still "long". The only safe way seems to be to use @James solution and use `-1ULL` if you wanna stay with the enum without casts and operator overloading and stuffs. – Johannes Schaub - litb Apr 28 '10 at 18:57
  • `-1ULL` looks promising, but in Visual Studio it doesn't work either. I'll try to post bug in VS bug tracker. – Kirill V. Lyadvinsky Apr 28 '10 at 19:11
  • Of course you would then need to implement all the other comparisons operator (boost.operators might help)... could you get away with a template using `boost::enable_if` and `boost::is_signed` / `boost::is_unsigned` (or perhaps just `boost::is_integral`) ? – Matthieu M. Apr 29 '10 at 08:53
  • @Matthieu yeah i suspect we could get away with a template like that. – Johannes Schaub - litb Apr 29 '10 at 10:55
1

According to Are C++ enums signed or unsigned? your compiler gets to choose whether enum is signed or not, though there are some comments saying that in C++0x you will be able to specify that it is unsigned.

Community
  • 1
  • 1
mathmike
  • 1,014
  • 5
  • 10
1

Per C++ Enumeration Declarations on MSDN:

enum EEE : unsigned {
    X1 = 1 
}; 
Gilles 'SO- stop being evil'
  • 104,111
  • 38
  • 209
  • 254
Zur
  • 11
  • 1
  • @KirillV.Lyadvinsky: really? It should. MSVC says it compiles this since MSVC2005. – Mooing Duck Dec 14 '12 at 19:13
  • 1
    I searched for ***unsigned*** in the reference, but it does not show up like you provide above. ***unsigned*** is only used once in a sentence. Are you certain that reference is correct? – jww Jul 06 '15 at 05:40
  • @jww Well, that sentence explains how it should be used. The reference to `type` is a reference to the schematic declaration at the very top of the article: `enum [tag] [: type] ...` So it is saying that `type` there can be any scalar signed or unsigned integral type. This *should* certainly work. It compiles for me on VS 2010, but it gives warning C4480 (nonstandard extension used: specifying underlying type for enum). – Cody Gray - on strike Mar 02 '16 at 07:50
0

Why not

enum EEE {
    X1 = 1,
    x = 2 // pick more descriptive name, a'course
};

or

if ( size_t( t ) < x )
Potatoswatter
  • 134,909
  • 25
  • 265
  • 421
  • 2
    How do you know that your enum values for the enum EEE are unsigned? They look like ints to me. – chollida Apr 28 '10 at 18:23
  • @chollida, the ultimate goal was to get rid of the warning, not to make it unsigned, i would suspect. His way does achieve that. – Johannes Schaub - litb Apr 28 '10 at 18:31
  • @cohollida: the question is how to make the enum type unsigned. That would imply he won't put negative values in, or he wants modulo arithmetic if he does. – Potatoswatter Apr 28 '10 at 18:44