C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Won't work, wy?

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Josh
Guest





PostPosted: Sat Jul 10, 2004 7:30 pm    Post subject: Won't work, wy? Reply with quote



Hello everyone,

I'm new to this group; I have a question:

suppose you had the following declaration:

enum FSAction
{ PROMPT, MOVE, DEL };

Now, suppose you declared a variable of this type as follows:

FSAction Action;

Finally, lets say you tried to read it from an ifstream object like this:

InputStream >> Action;

Well, you get the following error under VC++ 6.0:

error C2679: binary '>>' : no operator defined which takes a right-hand
operand of type 'enum FSAction' (or there is no acceptable conversion)

This sseemed strange to me since I thought the compiler automatically
converted enumerated types to integers when needed, but I tried the
following anyway:

InputStream >> (int) Action;

And got a similar error:

error C2679: binary '>>' : no operator defined which takes a right-hand
operand of type 'int' (or there is no acceptable conversion)


Hmm.... It doesn't work with ints now? What's wrong?

Thanks for any help you guys can give,

Josh




[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
John Potter
Guest





PostPosted: Sun Jul 11, 2004 10:29 am    Post subject: Re: Won't work, wy? Reply with quote



On 10 Jul 2004 15:30:25 -0400, "Josh" <rujones2 (AT) mail (DOT) comcast.net> wrote:

Quote:
suppose you had the following declaration:

enum FSAction
{ PROMPT, MOVE, DEL };

Now, suppose you declared a variable of this type as follows:

FSAction Action;

Finally, lets say you tried to read it from an ifstream object like this:

InputStream >> Action;

Well, you get the following error under VC++ 6.0:

error C2679: binary '>>' : no operator defined which takes a right-hand
operand of type 'enum FSAction' (or there is no acceptable conversion)

This sseemed strange to me since I thought the compiler automatically
converted enumerated types to integers when needed,

No. It will convert enumerated values to int values. It does not
convert types.

Quote:
but I tried the following anyway:

InputStream >> (int) Action;

And got a similar error:

error C2679: binary '>>' : no operator defined which takes a right-hand
operand of type 'int' (or there is no acceptable conversion)

Your statement is

InputStream >> static_cast<int>(Action);

which converts the value of the variable Action to an integer value.
There is no operator>> which takes an rvalue. The error message is a
bit misleading since there is an operator which takes a right-hand
operant of type int&. Notice the &, lvalue required.

Quote:
Hmm.... It doesn't work with ints now? What's wrong?

If you like living dangerously, you could claim that you know what
you are doing and demand that it accept your code.

InputStream >> reinterpret_cast<int&>(Action);

If the underlying type for that enum happens to be int in your
implementation with the current settings, it will work. It is
a bit safer to create a correct operator.

istream& operator>> (istream& is, FSAction& a) {
int v;
is >> v;
// Do something about invalid values.
a = static_cast<FSAction>(unsigned(v) % 3);
return is;
}

Note that the cast is required. Enumerator value will convert
to int value but int value does not convert to enumerator value.

John

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Victor Bazarov
Guest





PostPosted: Sun Jul 11, 2004 10:30 am    Post subject: Re: Won't work, wy? Reply with quote



"Josh" <rujones2 (AT) mail (DOT) comcast.net> wrote...
Quote:
I'm new to this group; I have a question:

suppose you had the following declaration:

enum FSAction
{ PROMPT, MOVE, DEL };

Now, suppose you declared a variable of this type as follows:

FSAction Action;

Finally, lets say you tried to read it from an ifstream object like this:

InputStream >> Action;

Well, you get the following error under VC++ 6.0:

error C2679: binary '>>' : no operator defined which takes a right-hand
operand of type 'enum FSAction' (or there is no acceptable conversion)

This sseemed strange to me since I thought the compiler automatically
converted enumerated types to integers when needed, but I tried the
following anyway:

InputStream >> (int) Action;

And got a similar error:

error C2679: binary '>>' : no operator defined which takes a right-hand
operand of type 'int' (or there is no acceptable conversion)


Hmm.... It doesn't work with ints now? What's wrong?

You're trying to read something from 'InputStream' into an r-value.

Casting a value into 'int' does not make a suggestion to the compiler
"look, it's a number I want, so enter the number and assign it to my
enumeration variable". What you really want is to do it yourself:

int i;
InputStream >> i;
Action = static_cast<FSAction>(i);

Of course, the user can enter 42 or 232134234, which is not necessarily
one of the enumerators in FSAction enumeration...

If sizeof(FSAction) == sizeof(int), you could try to do

InputStream >> static_cast<int&>(Action);

(notice that the cast is not to 'int' but to a reference to 'int')
but I wouldn't recommend it.

V


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
llewelly
Guest





PostPosted: Sun Jul 11, 2004 10:33 am    Post subject: Re: Won't work, wy? Reply with quote

"Josh" <rujones2 (AT) mail (DOT) comcast.net> writes:

Quote:
Hello everyone,

I'm new to this group; I have a question:

suppose you had the following declaration:

enum FSAction
{ PROMPT, MOVE, DEL };

Now, suppose you declared a variable of this type as follows:

FSAction Action;

Finally, lets say you tried to read it from an ifstream object like this:

InputStream >> Action;

There's an enum to int implicit conversion, but
ostream::operator>>(int&) takes an int& - and there's no enum &
to int& conversion.

Quote:

Well, you get the following error under VC++ 6.0:

error C2679: binary '>>' : no operator defined which takes a right-hand
operand of type 'enum FSAction' (or there is no acceptable conversion)

This sseemed strange to me since I thought the compiler automatically
converted enumerated types to integers when needed, but I tried the
following anyway:

InputStream >> (int) Action;

And got a similar error:

error C2679: binary '>>' : no operator defined which takes a right-hand
operand of type 'int' (or there is no acceptable conversion)
[snip]


You can't bind a reference to non-const a temporary. So
ostream::operator>>(int&) can't work for this call either.

You should write your own overloaded >> and << operators for
FSAction.

Try this on for size:

#include #include<ostream>

using namespace std;

enum FSAction
{ PROMPT, MOVE, DEL };

istream& operator>>(istream& in, FSAction& f)
{
int i;
in >> i;
f=static_cast<FSAction>(i);
return in;
}

ostream& operator<<(ostream& out, FSAction f)
{
switch(f)
{
case PROMPT:out<<"PROMPT";break;
case MOVE:out<<"MOVE";break;
case DEL:out<<"DEL";break;
default:out<<"Unknown";
}
return out;
}

int main()
{
FSAction f;
cin >> f;
cout << f << endl;
}

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Antoun Kanawati
Guest





PostPosted: Sun Jul 11, 2004 11:40 pm    Post subject: Re: Won't work, wy? Reply with quote

Josh wrote:
[snip]
Quote:
enum FSAction
{ PROMPT, MOVE, DEL };
FSAction Action;
InputStream >> Action;

error C2679: binary '>>' : no operator defined which takes a right-hand
operand of type 'enum FSAction' (or there is no acceptable conversion)
[snip]
InputStream >> (int) Action;

error C2679: binary '>>' : no operator defined which takes a right-hand
operand of type 'int' (or there is no acceptable conversion)

Hmm.... It doesn't work with ints now? What's wrong?

Because you need an /int&/, not a plain /int/. Furthermore, even if
you used an (int&) cast, you would be asking for trouble, because you
have no guarantee that FSAction is actually represented as int; it could
be short, or even char.

So, you need an extra int-typed variable to use with the input stream,
and then a conversion from int to FSAction. Something like this:

enum FSAction { PROMPT =0, MOVE =1, DEL =2};
int intAction;
InputStream >> intAction;
FSAction Action(static_cast<FSAction>(intAction));

--
Antoun Kanawati
[email]antounk.at (AT) comcast (DOT) dot.net[/email]
[remove .dot and .at before use]

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Ulrich Eckhardt
Guest





PostPosted: Sun Jul 11, 2004 11:42 pm    Post subject: Re: Won't work, wy? Reply with quote

Josh wrote:
Quote:
enum FSAction
{ PROMPT, MOVE, DEL };

Now, suppose you declared a variable of this type as follows:

FSAction Action;

Finally, lets say you tried to read it from an ifstream object like this:

InputStream >> Action;

Well, you get the following error under VC++ 6.0:

error C2679: binary '>>' : no operator defined which takes a right-hand
operand of type 'enum FSAction' (or there is no acceptable conversion)

Right, the enum is a new type for which there is no operator to read it
from a stream.

Quote:
This sseemed strange to me since I thought the compiler automatically
converted enumerated types to integers when needed,

Right, but you don't request much more. Consider this:
int n = Action;// Works, converted to int
Action = 5;//doesn't work, no implicit conversion from int

Reading it from a stream would require the second type of assignment and
thus fails.

Quote:
but I tried the following anyway:

InputStream >> (int) Action;

Here, something else goes wrong. This call is equivalent to this:
void function( int& );
function( (int)Action);

The point is, that '(int)Action' creates a temporary of type 'int'. Now,
there is a rule in C++ that you can't bind a temporary to a non-const
reference. That rule is mostly to protect people, because in above
example, if it did what you want, it would create the temporary, read it
from a stream and then discard(!) it. It will not be written back to the
original value.

Quote:
And got a similar error:

error C2679: binary '>>' : no operator defined which takes a right-hand
operand of type 'int' (or there is no acceptable conversion)


Hmm.... It doesn't work with ints now? What's wrong?

Yes, compiler error messages sometimes aren't worth anything....

Now, the only thing you need is to define an operator>> for your
enumeration.
istream& operator>>(istream& in, FSAction& action)
{
int temp;
if( in >> temp)
{
if( ... )// check for valid range
action = static_cast<FSAction>(temp);
else
in.clear(in.rdstate()|ios_base::failbit);
}
return in;
}

Uli

--
Questions ?
see C++-FAQ Lite: http://parashift.com/c++-faq-lite/ first !


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
John Potter
Guest





PostPosted: Mon Jul 12, 2004 12:17 am    Post subject: Re: Won't work, wy? Reply with quote

On 11 Jul 2004 06:30:07 -0400, "Victor Bazarov"
<v.Abazarov (AT) comAcast (DOT) net> wrote:

Quote:
If sizeof(FSAction) == sizeof(int), you could try to do

InputStream >> static_cast<int&>(Action);

(notice that the cast is not to 'int' but to a reference to 'int')
but I wouldn't recommend it.

How do you expect to get that past a compiler?

John

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Victor Bazarov
Guest





PostPosted: Mon Jul 12, 2004 11:17 am    Post subject: Re: Won't work, wy? Reply with quote

"John Potter" <jpotter (AT) falcon (DOT) lhup.edu> wrote...
Quote:
On 11 Jul 2004 06:30:07 -0400, "Victor Bazarov"
[email]v.Abazarov (AT) comAcast (DOT) net[/email]> wrote:

If sizeof(FSAction) == sizeof(int), you could try to do

InputStream >> static_cast<int&>(Action);

(notice that the cast is not to 'int' but to a reference to 'int')
but I wouldn't recommend it.

How do you expect to get that past a compiler?

By changing static_cast to reinterpret_cast, but then again,
it's undefined behaviour, probably.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Antoun Kanawati
Guest





PostPosted: Mon Jul 12, 2004 9:55 pm    Post subject: Re: Won't work, wy? Reply with quote

Victor Bazarov wrote:
Quote:
If sizeof(FSAction) == sizeof(int), you could try to do

InputStream >> static_cast<int&>(Action);
How do you expect to get that past a compiler?

By changing static_cast to reinterpret_cast, but then again,
it's undefined behaviour, probably.

This is undefined behavior. C++ does not guarantee any particular
integral representation of enumrated types; even the same compiler
may use different representations for different enums, depending
on a variety of factors.

And, unlike errors and similarly unambiguous terms, "undefined
behavior" can mean anything, including doing precisely what you
were expecting... until the next compiler upgrade or platform
change. I believe that the other term is "implementation defined";
which sounds less ominous than "undefined", but is subject to
the same uncertainties when you change compiler options, versions,
or platforms.

In practice, nothing is undefined. It is the number of possible
definitions and their variability that creates problems.
--
Antoun Kanawati
[email]antounk.at (AT) comcast (DOT) dot.net[/email]
[remove .dot and .at before use]

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
kanze@gabi-soft.fr
Guest





PostPosted: Tue Jul 13, 2004 9:16 pm    Post subject: Re: Won't work, wy? Reply with quote

Antoun Kanawati <antounk (AT) comcast (DOT) net> wrote

Quote:
Victor Bazarov wrote:
If sizeof(FSAction) == sizeof(int), you could try to do

InputStream >> static_cast<int&>(Action);
How do you expect to get that past a compiler?

By changing static_cast to reinterpret_cast, but then again,
it's undefined behaviour, probably.

This is undefined behavior. C++ does not guarantee any particular
integral representation of enumrated types; even the same compiler may
use different representations for different enums, depending on a
variety of factors.

That's not quite true. The C++ standard uniquely specifies the numeric
value of each enum constant. It also requires that an enum be
implemented as an underlying integral type, which means that it must use
a binary representation. Finally, the standard requires that the enum
be capable of holding all possible values which could result from
bitwise or'ing of all of the declared enum values. About the only
thing, in fact, that the standard leaves open is the size of the enum
type.

Of course, the size alone is largely sufficient for the undefined
behavior to occur:-).

Quote:
And, unlike errors and similarly unambiguous terms, "undefined
behavior" can mean anything, including doing precisely what you were
expecting... until the next compiler upgrade or platform change. I
believe that the other term is "implementation defined"; which sounds
less ominous than "undefined", but is subject to the same
uncertainties when you change compiler options, versions, or
platforms.

Sort of. With regards to the standard, undefined behavior means that
the implementation can do anything, and doesn't have to document it, nor
even be consistent. An implementation CAN define undefined behavior --
most do for certain things (e.g. threading). Implementation defined
means that the implementation MUST define and document what it does,
typically from a closed set of possibilities. Implementation defined
can (and often does, e.g. the signedness of a char) depend on compiler
options.

One problem we have in discussions is that in everyday language, we
refer to undefined behavior defined by the implementation as
implementation defined.

Quote:
In practice, nothing is undefined. It is the number of possible
definitions and their variability that creates problems.

This is trivially true in the sense that the computer has a finite
number of states, and whatever you get will depend on the state of the
computer when you execute the code. On my computer, the number of
states is something like a 1 followed by 1,200,000,000,000 zeros. Not
counting the disk. Which is close enough to undefined for me.

--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Antoun Kanawati
Guest





PostPosted: Wed Jul 14, 2004 9:47 am    Post subject: Re: Won't work, wy? Reply with quote

[email]kanze (AT) gabi-soft (DOT) fr[/email] wrote:
Quote:
Antoun Kanawati <antounk (AT) comcast (DOT) net> wrote in message

This is undefined behavior. C++ does not guarantee any particular
integral representation of enumrated types; even the same compiler may
use different representations for different enums, depending on a
variety of factors.

That's not quite true. The C++ standard uniquely specifies the numeric
value of each enum constant. It also requires that an enum be
implemented as an underlying integral type, ...
.....[snip]...
Of course, the size alone is largely sufficient for the undefined
behavior to occur:-).

I understand that the standard needs to make certain things absolutely
unambiguous. However, when discussing whether enum& and int& are
"compatible", the assumption of integral representation of enums is
already taken for granted; the question is: is it always int, or could
it be something else? The standard clearly says that it could be.

So, let me restate, and see if this works out OK for you:

C++ does not guarantee a specific integral representation of
enumerated types; even the same compiler may use different
integral representations for different enums, depending on
a variety of factors.

Quote:
In practice, nothing is undefined. It is the number of possible
definitions and their variability that creates problems.

This is trivially true in the sense that the computer has a finite
number of states, and whatever you get will depend on the state of the
computer when you execute the code. On my computer, the number of
states is something like a 1 followed by 1,200,000,000,000 zeros. Not
counting the disk. Which is close enough to undefined for me.

My comment is a "reaction" to the "undefined may reformat your drive"
as the canonical example, or the astronomical numbers that are bandied
about. In practice, the fuzz-ball of uncertainty around a particular
form of undefined behavior is rarely of astronomical size. In the
example we're using here: messing around with an enum value through an
int&, there is a non-trivial probability of memory corruption of limited
scope, as well as the potential for misaligned access.

I am quite happy with the standard's concept of "undefined" [anything,
including the most absurd and unthinkable]; it's quite inclusive, and
I can't get a false sense of security out of it Smile
--
Antoun Kanawati
[email]antounk.at (AT) comcast (DOT) dot.net[/email]
[remove .dot and .at before use]

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Allan W
Guest





PostPosted: Fri Jul 16, 2004 12:20 am    Post subject: Re: Won't work, wy? Reply with quote

llewelly <llewelly.at (AT) xmission (DOT) dot.com> wrote
Quote:
Try this on for size:

#include<iostream
#include
using namespace std;

enum FSAction
{ PROMPT, MOVE, DEL };

istream& operator>>(istream& in, FSAction& f)
{
int i;
in >> i;
f=static_cast<FSAction>(i);
return in;
}

This is okay. It reads an integer from the stream and casts it to an
FSAction.

One risk here is maintenance. Assume we use this function to save the
value of enumerations to an output stream. If the enumerations in
FSAction ever change, it invalidates them all. If you re-read the
old file from a newly-compiled program, you get the wrong values.
(Realistically, one way to solve this might be to add a comment to the
enumeration:
// Values saved on disk, so DO NOT CHANGE THESE VALUES
or something similar.)

Another issue is interactive I/O. Here you want the user to type
0 for PROMPT, 1 for MOVE, or 2 for DEL -- and you don't even
validate that the user chose one of these values.

Quote:
ostream& operator<<(ostream& out, FSAction f)
{
switch(f)
{
case PROMPT:out<<"PROMPT";break;
case MOVE:out<<"MOVE";break;
case DEL:out<<"DEL";break;
default:out<<"Unknown";
}
return out;
}

This is good too. It clearly translates the enumerations into names that
the user can understand.
cout << "The next action is " << myAction << endl;
makes sense for interactive users, and it can also be used to save
the values in data files.

The problem comes when you mix the two.

Quote:
int main()
{
FSAction f;
cin >> f;
cout << f << endl;
}

When you run this program, it sits idly by (without even a prompt!),
waiting for the user to type a number. When she finally does, it
translates it into text, and then exits.

A worse example involves saving it to disk.

int main() {
FSAction f = PROMPT;
{ ofstream o("Action.dat");
o << f << endl;
}

{ ifstream i("Action.dat");
i >> f; // Fails
}
}

The problem is that when we wrote the action out, we wrote the letters
P, R, O, M, P, T. When we read the action back in, we were looking for
an integer.

For this to work, your output and input routines need to be consistent.
Write out something that can be parsed when you read it back in!

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Michiel Salters
Guest





PostPosted: Fri Jul 16, 2004 1:58 pm    Post subject: Re: Won't work, wy? Reply with quote

Antoun Kanawati <antounk (AT) comcast (DOT) net> wrote

Quote:
In practice, the fuzz-ball of uncertainty around a particular
form of undefined behavior is rarely of astronomical size. In the
example we're using here: messing around with an enum value through an
int&, there is a non-trivial probability of memory corruption of limited
scope, as well as the potential for misaligned access.

That is far from an inclusive list, though. For instance, the consequences
of misaligned access may include a transfer to an exception handler, the
optimizer may get loads/stores wrong when doing type-analysis (look,
there's an int& but no int on the stack so the int& must point oustide
the function - let's optimize the load). Storing though an int& when
in reality the object is smaller and located on a page boundary may
trigger a invalid page fault, or just clobber something in the page
file, or assuming a sufficently trusting OS, outside the page file.

Undefined behavior really is a fuzz-ball : No sharp boundaries,
there may be a compact core of typical failure modes but there usually
are rare outliers everywhere.

Regards,
Michiel Salters

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Antoun Kanawati
Guest





PostPosted: Sat Jul 17, 2004 10:08 am    Post subject: Re: Won't work, wy? Reply with quote

Michiel Salters wrote:

Quote:
Antoun Kanawati <antounk (AT) comcast (DOT) net> wrote


In practice, the fuzz-ball of uncertainty around a particular
form of undefined behavior is rarely of astronomical size. In the
example we're using here: messing around with an enum value through an
int&, there is a non-trivial probability of memory corruption of limited
scope, as well as the potential for misaligned access.

That is far from an inclusive list, though. For instance, the consequences
of misaligned access may include a transfer to an exception handler, the
optimizer may get loads/stores wrong when doing type-analysis (look,
there's an int& but no int on the stack so the int& must point oustide
the function - let's optimize the load). Storing though an int& when
in reality the object is smaller and located on a page boundary may
trigger a invalid page fault, or just clobber something in the page
file, or assuming a sufficently trusting OS, outside the page file.

Undefined behavior really is a fuzz-ball : No sharp boundaries,
there may be a compact core of typical failure modes but there usually
are rare outliers everywhere.

If you were trying to disagree, all you did is increase the definition
of the particular fuzz-ball.

All I said is "the fuzz-ball of uncertainty is not of astronomical
size". I did not preclude uncertainty, nor did I say that "undefined"
is anywhere close to well-defined.

Philosophically speaking, undefined behavior needs no definition; in
fact, it precludes definition.

In practice, we know that not all manifestations of undefined behavior
are the same. A null-pointer access has well known manifestations in
the usual program on the usual computer. Alignment errors often have
well known manifestations once you define the platform. Even a hard
to observe small-scale memory corruption is detectable when you strap
on Purify or a similar tool.

Only in the standard, which has to be universal, does "undefined" need
to be so mystically undefined.
--
Antoun Kanawati
[email]antounk.at (AT) comcast (DOT) dot.net[/email]
[remove .dot and .at before use]

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.