enums in C and C++

S

Simon Elliott

I'm porting thousands of lines of legacy C code to C++. One makor issue
I've got is that of enums being treated differently in C and C++.
There's an automatic cast from int to enum in C but not in C++. The
code is full of constructs like this:

enum { CARROT=0x01,TURNIP=0x02,PARSNIP=0x04,SPROUT=0x08 } garden_veg;

garden_veg = CARROT|PARSNIP; /* Fine in C, but not in C++ */

Do I really have to trawl through all this code and put in many
hundreds of casts, or is there something clever I can do to get round
this?
 
V

Victor Bazarov

Simon said:
I'm porting thousands of lines of legacy C code to C++. One makor issue
I've got is that of enums being treated differently in C and C++.
There's an automatic cast from int to enum in C but not in C++. The
code is full of constructs like this:

enum { CARROT=0x01,TURNIP=0x02,PARSNIP=0x04,SPROUT=0x08 } garden_veg;

garden_veg = CARROT|PARSNIP; /* Fine in C, but not in C++ */

Do I really have to trawl through all this code and put in many
hundreds of casts, or is there something clever I can do to get round
this?

The only "clever" thing to do is to keep this C (if it worked before, why
change?)

V
 
A

Artie Gold

Simon said:
I'm porting thousands of lines of legacy C code to C++. One makor issue
I've got is that of enums being treated differently in C and C++.
There's an automatic cast from int to enum in C but not in C++. The
code is full of constructs like this:

enum { CARROT=0x01,TURNIP=0x02,PARSNIP=0x04,SPROUT=0x08 } garden_veg;

garden_veg = CARROT|PARSNIP; /* Fine in C, but not in C++ */

Do I really have to trawl through all this code and put in many
hundreds of casts, or is there something clever I can do to get round
this?
Why are you bothering to port C code to C++?* Leave it in C and call
what you need (from C++).

HTH,
--ag

* - No slam on C++ intended; just a practical comment.
 
T

Thierry Miceli

enum { CARROT=0x01,TURNIP=0x02,PARSNIP=0x04,SPROUT=0x08 } garden_veg;
garden_veg = CARROT|PARSNIP; /* Fine in C, but not in C++ */

Do I really have to trawl through all this code and put in many
hundreds of casts, or is there something clever I can do to get round
this?

If you really want to convert the code to C++ you could try to redefine the
'|' operator for the enum. e.g:

enum GardenVegetables { CARROT=0x01,TURNIP=0x02,PARSNIP=0x04,SPROUT=0x08 };

GardenVegetables operator|(GardenVegetables veg1, GardenVegetables veg2)
{
return (GardenVegetables) ((int)veg1 | (int)veg2);
}

Regards,

Thierry
www.ideat-solutions.com
 
?

=?ISO-8859-15?Q?Juli=E1n?= Albo

Simon Elliott said:
enum { CARROT=0x01,TURNIP=0x02,PARSNIP=0x04,SPROUT=0x08 } garden_veg;

garden_veg = CARROT|PARSNIP; /* Fine in C, but not in C++ */

Do I really have to trawl through all this code and put in many
hundreds of casts, or is there something clever I can do to get round
this?

You can write a garden_veg operator | (garden_veg, garden_veg)
 
I

Ioannis Vranos

Simon said:
I'm porting thousands of lines of legacy C code to C++. One makor issue
I've got is that of enums being treated differently in C and C++.
There's an automatic cast from int to enum in C but not in C++. The
code is full of constructs like this:

enum { CARROT=0x01,TURNIP=0x02,PARSNIP=0x04,SPROUT=0x08 } garden_veg;

garden_veg = CARROT|PARSNIP; /* Fine in C, but not in C++ */

Do I really have to trawl through all this code and put in many
hundreds of casts, or is there something clever I can do to get round
this?



Well, a quick fix could be something like:


template <class T>
inline T enum_cast_or(T a, T b) { return static_cast<T>(a|b); }


enum SomeEnum { CARROT=0x01, TURNIP=0x02, PARSNIP=0x04, SPROUT=0x08 };


SomeEnum garden_veg = enum_cast_or(CARROT,PARSNIP);
 
J

Jay Nabonne

I'm porting thousands of lines of legacy C code to C++. One makor issue
I've got is that of enums being treated differently in C and C++.
There's an automatic cast from int to enum in C but not in C++. The
code is full of constructs like this:

enum { CARROT=0x01,TURNIP=0x02,PARSNIP=0x04,SPROUT=0x08 } garden_veg;

garden_veg = CARROT|PARSNIP; /* Fine in C, but not in C++ */

Do I really have to trawl through all this code and put in many
hundreds of casts, or is there something clever I can do to get round
this?

It's not really using it as an enum (once you '|' them, it's not really a
value in the enumeration anymore).

Do:

enum garden_veg_enum { CARROT=0x01,TURNIP=0x02,PARSNIP=0x04,SPROUT=0x08 };

int garden_veg;

and let it go... :)

- Jay
 
J

JKop

Thierry Miceli posted:
If you really want to convert the code to C++ you could try to redefine
the '|' operator for the enum. e.g:

enum GardenVegetables {
CARROT=0x01,TURNIP=0x02,PARSNIP=0x04,SPROUT=0x08 };

GardenVegetables operator|(GardenVegetables veg1, GardenVegetables
veg2) {
return (GardenVegetables) ((int)veg1 | (int)veg2);
}


return static_cast<GardenVegetables>( ( static_cast<int>(veg1) |
static_cast<int>(veg2) ) );


C++, not C/C++ ;-D


-JKop
 
S

Siemel Naran

JKop said:
Thierry Miceli posted:


return static_cast<GardenVegetables>( ( static_cast<int>(veg1) |
static_cast<int>(veg2) ) );


C++, not C/C++ ;-D

It seems fine to use C style casts for converting one integer/float type to
another. Imagine that there exists a constructor
GardenVegetables::GardenVegetables(int). Only for converting one
pointer/reference type to another do I use one of the C++ style casts
(usually static_cast, but sometimes reinterpret_cast).

Also, instead of

one could say

return GardenVegetables ( (int(veg1) | int(veg2)) );

but neither way is superior, though I'm not sure if this second way is
allowed in C.


Similarly, "(size_t)i" which is equivalent to "size_t(i)" where i is an int,
also seems fine to me as a good style of C++.
 
J

JKop

Similarly, "(size_t)i" which is equivalent to "size_t(i)" where i is an
int, also seems fine to me as a good style of C++.


See but that's why "reinterpret_cast" was given such a horrid name:


float p;

int* k = (int*) &p; //legal

int* k = int*(&p) ; // no can do


To achieve this, you need to be horrid:

int* k = reinterpret_cast<int* const>(&p);


I myself never use (int). Here's how I do it:

Step 1) Use "static_cast". If rejected go to step 2.

Step 2) Use "reinterpret_cast".


I've never had to use "dynamic_cast" so far!


-JKop


-JKop
 
T

Thierry Miceli

GardenVegetables operator|(GardenVegetables veg1, GardenVegetables
return static_cast<GardenVegetables>( ( static_cast<int>(veg1) |
static_cast<int>(veg2) ) );


C++, not C/C++ ;-D
I agree, I sacrificed purity for readability.

Thierry
 
S

Siemel Naran

JKop said:
See but that's why "reinterpret_cast" was given such a horrid name:


float p;

int* k = (int*) &p; //legal

int* k = int*(&p) ; // no can do

I agree that for casting between pointer and reference types, it's good to
use static_cast or reinterpret_cast. But for casting between value types, C
style casts which behave like constructors, seem perfectly fine.

To achieve this, you need to be horrid:

int* k = reinterpret_cast<int* const>(&p);


I myself never use (int). Here's how I do it:

Step 1) Use "static_cast". If rejected go to step 2.

Step 2) Use "reinterpret_cast".

Agreed for pointer types only.
I've never had to use "dynamic_cast" so far!

It arises when writing generic code, and you can't or don't want to edit the
base class by continually adding virtual functions to it.
 
I

Ioannis Vranos

Siemel said:
I agree that for casting between pointer and reference types, it's good to
use static_cast or reinterpret_cast. But for casting between value types, C
style casts which behave like constructors, seem perfectly fine.


C++ newer casts are still better.
 
S

Simon Elliott

On 28/10/2004, Simon Elliott wrote:
[snip]

Thanks for all the responses to this. I'm still unsure about how to
proceed because there are lots of different enums which are used in
lots of different ways. With the current compiler (BCB3) I have the
(slightly grubby) option of suppressing the warning and leaving
everything as it is. But it's possible that other compilers won't let
me do this.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,228
Members
46,817
Latest member
AdalbertoT

Latest Threads

Top