How to use stream with enum?

P

PengYu.UT

Hi,

I have some problem when I use enum with stream. The code segment is
listed below. I know if I change the first line to "int op;", there
will not be any error. However, what I really want is of enum type. Is
there any other way to fix this problem?

Best wishes,
Peng

rect_type op;// int op;
ss >> op;//std::istringstream ss; compile time error

//with the declaration of

enum rect_type{
CANONICAL,

TOP_LEFT,
BOTTOM_LEFT,
TOP_RIGHT,
BOTTOM_RIGHT,

TOP_MIDDLE,
BOTTOM_MIDDLE,
LEFT_MIDDLE,
RIGHT_MIDDLE,

CENTRAL
};
 
B

Bob Hairgrove

Hi,

I have some problem when I use enum with stream. The code segment is
listed below. I know if I change the first line to "int op;", there
will not be any error. However, what I really want is of enum type. Is
there any other way to fix this problem?

Best wishes,
Peng

rect_type op;// int op;
ss >> op;//std::istringstream ss; compile time error

//with the declaration of

enum rect_type{
CANONICAL,

TOP_LEFT,
BOTTOM_LEFT,
TOP_RIGHT,
BOTTOM_RIGHT,

TOP_MIDDLE,
BOTTOM_MIDDLE,
LEFT_MIDDLE,
RIGHT_MIDDLE,

CENTRAL
};

I bet you also tried overloading the global operator>> (taking the
first argument of type "ostream &" and a second argument of type
"rect_type const &")? I would. But you might not like the results. It
is indeed possible, but the big problem is that there is no built-in
conversion from int to enum in C++.

Somewhere down the line, you must convert your input from an integral
tye to type rect_type, and there is no "easy" way to do this except to
provide a conversion function taking some integer type as an argument,
returning a rect_type, and containing nothing but a huge switch
statement more or less duplicating your enum definition.

You could hide the conversion function in some kind of policy class,
but it might not be worth the effort.
 
I

Ian

Bob said:
I bet you also tried overloading the global operator>> (taking the
first argument of type "ostream &" and a second argument of type
"rect_type const &")? I would. But you might not like the results. It
is indeed possible, but the big problem is that there is no built-in
conversion from int to enum in C++.

Somewhere down the line, you must convert your input from an integral
tye to type rect_type, and there is no "easy" way to do this except to
provide a conversion function taking some integer type as an argument,
returning a rect_type, and containing nothing but a huge switch
statement more or less duplicating your enum definition.
Not such a big deal for this example as the enum values are contiguous,
so you only have to check against min and max values and do a static_cast.

Ian
 
D

davidrubin

Bob said:
Hi,

I have some problem when I use enum with stream. The code segment is
listed below. I know if I change the first line to "int op;", there
will not be any error. However, what I really want is of enum type. Is
there any other way to fix this problem?

Best wishes,
Peng

rect_type op;// int op;
ss >> op;//std::istringstream ss; compile time error

//with the declaration of

enum rect_type{
CANONICAL,

TOP_LEFT,
BOTTOM_LEFT,
TOP_RIGHT,
BOTTOM_RIGHT,

TOP_MIDDLE,
BOTTOM_MIDDLE,
LEFT_MIDDLE,
RIGHT_MIDDLE,

CENTRAL
};
[snip]
Somewhere down the line, you must convert your input from an integral
tye to type rect_type, and there is no "easy" way to do this except to
provide a conversion function taking some integer type as an argument,
returning a rect_type, and containing nothing but a huge switch
statement more or less duplicating your enum definition.

This "function" is called casting! But, you do need to do a little
work: make your enum into an attribute class, and provide an 'isValid'
method:

struct RectType {
enum Value {
// enumerated values
};

static bool isValid(int value);
// Return 'true' if 'the specified value' is a valid 'RectType'
// and 'false' otherwise.
};

bool RectType::isValid(int value)
{
return (0 <= value <= CENTRAL); // depending on enumerated values
}

Notice that 'isValid' does not need to take 'RectType::Value' because
an object of type 'RectType' is always valid.

Then:

RectType::Value rectType; // initial value?
int value = -1;
stream >> value;
if (RectType::isValid(value)) {
rectType = (RectType::Value)value;
}

It helps to have some enumerated value like 'UNSPECIFIED' to be used as
an initial value in cases like the one above. Otherwise, you need to do
some fancier error handling.

Of course if you don't care about checking whether 'value' is a valid
'RectType', you just skip the if-clause.

/david
 
I

Ian

This "function" is called casting! But, you do need to do a little
work: make your enum into an attribute class, and provide an 'isValid'
method:

struct RectType {
enum Value {
// enumerated values
};

static bool isValid(int value);
// Return 'true' if 'the specified value' is a valid 'RectType'
// and 'false' otherwise.
};

bool RectType::isValid(int value)
{
return (0 <= value <= CENTRAL); // depending on enumerated values
}

Notice that 'isValid' does not need to take 'RectType::Value' because
an object of type 'RectType' is always valid.

Then:

RectType::Value rectType; // initial value?
int value = -1;
stream >> value;
if (RectType::isValid(value)) {
rectType = (RectType::Value)value;

It would be better style to use a static_cast here.

Ian
 
A

Alan Johnson

bool RectType::isValid(int value)
{
return (0 <= value <= CENTRAL); // depending on enumerated values
}

This will not work. Try, instead:

return (0 <= value) && (value <= CENTRAL) ;

-Alan
 

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

Forum statistics

Threads
474,297
Messages
2,571,530
Members
48,251
Latest member
Amelia8778

Latest Threads

Top