Does GCC assign any type to enums that can be specified in an assignment operator?

View: New views
5 Messages — Rating Filter:   Alert me  

Does GCC assign any type to enums that can be specified in an assignment operator?

by michael.a :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

The Microsoft compiler treats enums as int types (or some type) for purpose of assignment, but GCC does not. Best I can figure, GCC treats an enum value assignment as ambiguous when presented with more than one integral assignment operator. Is there a type I can define an assignment operator for which will take precedence for enum values?

If not it woud appear the only alternative is to manually typecast every instance of an enum value, or create a special assignment operator explicitly for enums (not with the = operator)

Either way that would be a ton of work for me. Any ideas?

Re: Does GCC assign any type to enums that can be specified in an assignment operator?

by michael.a :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


> > Does GCC assign any type to enums that can be specified in an  assignment
> operator?
>
> I'm not sure I understand the question.  I assume a C++ context, and not a C
> context (which has different rules regarding enum types).
>
> What is the use case scenario?  Do you mean something like this...
>
> - - - - -
> enum Foo { Uno, Dos, Tres };
>
> class Bar
> {
>   int m;
> public:
>   Bar() : m(Uno) { }
>   Bar(Foo foo) : m(foo) { }
>   Bar(Bar const& bar) : m(bar.m) { }
>   Bar& operator = (Foo foo) { m = foo; return *this; }
>   operator Foo() const { return Foo(m); }
> };
> - - - - -
>
> --Eljay
>

I'm sorry, perhaps to be more specific, I was referring more so (if not entirely) to anonymous enums (never really ever use tagged enums)

Since asked, basicly imagine this:

 enum{ Uno, Dos, Tres }; //anonymous
 
 class Bar
 {
   int m;
 public:
   Bar& operator = (unsigned int foo) { m = foo; return *this; }
   Bar& operator = (signed int foo) { m = foo; return *this; }
 };

You could substitute pretty much any number of integral assignment operators.

Now say:

Bar bar; bar = Uno; //error: assignment operators are ambiguous

Whereas, with the Windows compiler (msvc for short) Uno will be treated as an int (signed -- perhaps more specifically a const long int if the option exists) ...basicly msvc resolves this ambiguity by choosing the closest match on a well defined top down prioritized basis, whereas GCC just gives up and declares ambiguity.

Its mostly just annoying... turns out though I already had an alternative assignment for all of the cases I've ran into so far during the porting process.

So I hope that clears everything up. Appreciate your curiosity.

sincerely,

michael

PS: I will go ahead and repost this in the Nabble forums if it doesn't pop up (my apologies if it is multiposted to the mailing lists etc)



Re: Does GCC assign any type to enums that can be specified in an assignment operator?

by John (Eljay) Love-Jensen :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi Michael,

The type for the enum, as given, will be signed int.

Now if you want the enum to be ambiguous, you can do something like this:

enum { Uno = -1, Dos, Tres = 0x80000000 };

That will cause an ambiguous overload of the signed & unsigned assignment
operators, since the 0x80000000 will be taken to be an unsigned int as per
the standard C/C++ interpretation rules.  (Assuming a 32-bit int platform.)

Is that the situation you are running into?

You can "fix" it by doing:

enum { Uno = -1, Dos, Tres = int(0x80000000) };

--Eljay


Re: Does GCC assign any type to enums that can be specified in an assignment operator?

by michael.a :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

John Love-Jensen wrote:
Hi Michael,

The type for the enum, as given, will be signed int.

Now if you want the enum to be ambiguous, you can do something like this:

enum { Uno = -1, Dos, Tres = 0x80000000 };

That will cause an ambiguous overload of the signed & unsigned assignment
operators, since the 0x80000000 will be taken to be an unsigned int as per
the standard C/C++ interpretation rules.  (Assuming a 32-bit int platform.)

Is that the situation you are running into?

You can "fix" it by doing:

enum { Uno = -1, Dos, Tres = int(0x80000000) };

--Eljay
Wow, really? I didn't realize that was possible. I'll have to look into that, but in this case, there is also an operator for unsigned int assignment, so it shoud resolve to that operator even in this case. I think before I had a 'long' in the int types I was using, so that might've made a difference. I subsequently removed it though. I'm not exactly sure how to guarantee a 32bit / 64bit value across 32/64bit platforms with gcc.

GCC seems to resolve a 0 as a long int rather than just int.

I could try myself naturally, but I don't suppose its possible to cast enum values to say a char or short type? Would a pointer type or something larger than 32bits be accomodated too?

Re: Does GCC assign any type to enums that can be specified in an assignment operator?

by John (Eljay) Love-Jensen :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi Michael,

> ... but in this case, there is also an operator for unsigned int
> assignment, so if it shoud resolve to that operator even in this case.

No, it can't resolve because it is ambiguous.

The TYPE of Uno, Dos and Tres is all the same.  On my platform, they're all
signed long long (a 64-bit signed int).

If you want them to each have their own distinct type (which then would not
be ambiguous), you'd have to do:

enum { Uno = -1 }; // signed int
enum { Dos }; // signed int
enum { Tres = 0x80000000 }; // unsigned int

But better yet (far, far better!), don't use an anonymous enum, use a
typename'd enum, and then use that typename specifically in your assignment
operator.

> I think before I had a 'long' in the int types I was using, so that might've
> made a difference.

A long is not legal value for an enum in C89.  (I'm not sure about C99.)
But it is a legal value for C++.

> GCC seems to resolve a 0 as a long int rather than just int.

By itself?  No, a 0 is type biased as an int.  A 0L is type biased as a long
int.

In an enum?  In C++, the type of an enum depends on the values enumerated
taken as a set (with a few caveats and sharp edges for the unwary).

> I could try myself naturally, but I don't suppose its possible to cast enum
> values to say a char or short type?

Something like...

enum signed char { Uno, Dos, Tres };

...or...

signed char enum { Uno, Dos, Tres };

...?

That'd be nice.  A previous compiler I used on the Amiga had an extension
like that, which at that time I used heavily.  Alas, it is not part of the
standard.

> Would a pointer type or something larger than 32bits be accomodated too?

I don't think you can have an enum of pointers.

For C89, if your int size is larger than 32-bit, then that int size in enums
is accommodated.

For C++, it allows enums on long int, and GCC has an extension support for
long long.  Depending on your platform, if long int or long long is larger
than 32-bit, then something larger than 32-bits is accommodated.

Keep in mind that "larger than 32-bits" is not the C/C++ way of thinking
about things.  An int is the natural word size of the architecture (minimum
of 16-bit).  So an int could be 16-bit, or 32-bit, or 64-bit (we're now
seeing 64-bit natural word size architectures in personal computers on
people's desktops), or 128-bit, or 256-bit.

And that's just considering the "8-bit per byte" octet architectures, and
discounting the other bits-per-byte sized architectures.

If you need specific bit-sizes, look at C99's <stdint.h> and the more
extensive companion <inttypess.h>.  If you are doing C++, I recommend
mimicking <stdint.h> ... but PLEASE put the typedef's in your own namespace,
not in the global namespace and not in std namespace.  Or better yet, use
BOOST's "boost/cstdint.hpp" which has done the work for you already.

Sincerely,
--Eljay