Enum oddity

F

Francesco

Hi there,
I was trying to work around the fact that there is no implicit
conversion from int to enum, and I stomped on something odd.
(actually, in the code I'm about to post, I snipped out the ctor
taking an int, which would work around the missing implicit conversion
- here the issue is different)

See this really simple snippet:

-------
#include <iostream>

using namespace std;

class Color {
public:
enum color { black, white };
color c;
Color(color cc = black) : c (cc) {}
};

int main()
{
int i = 0;
Color col(Color::color(i));
cout << col.c << endl;
return 0;
}
-------

Since it didn't compile on my old MinGW release, I've tried it on
Comeau Online, and it happened to give just the same results:

-------
Comeau C/C++ 4.3.10.1 (Oct 6 2008 11:28:09) for
ONLINE_EVALUATION_BETA2
Copyright 1988-2008 Comeau Computing. All rights reserved.
MODE:strict errors C++ C++0x_extensions

"ComeauTest.c", line 16: error: expression must have class type
cout << col.c << endl;
^

"ComeauTest.c", line 14: warning: variable "i" was declared but never
referenced
int i = 0;
^

1 error detected in the compilation of "ComeauTest.c".

In strict mode, with -tused, Compile failed
Hit the Back Button to review your code and compile options.
Compiled with C++0x extensions enabled.
-------

Changing this:
Color col(Color::color(i));
to this:
Color col(Color::black);
lets it compile with no problem whatsoever.


What do you think about? Should I report it to the Comeau team?

Cheers
Francesco
 
F

Francesco

Hi there,
I was trying to work around the fact that there is no implicit
conversion from int to enum, and I stomped on something odd.
(actually, in the code I'm about to post, I snipped out the ctor
taking an int, which would work around the missing implicit conversion
- here the issue is different)

See this really simple snippet:

-------
#include <iostream>

using namespace std;

class Color {
  public:
  enum color { black, white };
  color c;
  Color(color cc = black) : c (cc) {}

};

int main()
{
    int i = 0;
    Color col(Color::color(i));
    cout << col.c << endl;
    return 0;}

-------

Since it didn't compile on my old MinGW release, I've tried it on
Comeau Online, and it happened to give just the same results:

-------
Comeau C/C++ 4.3.10.1 (Oct  6 2008 11:28:09) for
ONLINE_EVALUATION_BETA2
Copyright 1988-2008 Comeau Computing.  All rights reserved.
MODE:strict errors C++ C++0x_extensions

"ComeauTest.c", line 16: error: expression must have class type
      cout << col.c << endl;
              ^

"ComeauTest.c", line 14: warning: variable "i" was declared but never
referenced
      int i = 0;
          ^

1 error detected in the compilation of "ComeauTest.c".

In strict mode, with -tused, Compile failed
Hit the Back Button to review your code and compile options.
Compiled with C++0x extensions enabled.
-------

Changing this:
    Color col(Color::color(i));
to this:
    Color col(Color::black);
lets it compile with no problem whatsoever.

What do you think about? Should I report it to the Comeau team?

Cheers
Francesco

Also changing this:
Color col(Color::color(i));
to this (adding the parentheses):
Color col((Color::color(i)));
solves the problem.

Hence this must me a parsing problem, but I don't see how:
Color col(Color::color(i));
could be considered a function declaration.

So, what's the issue here?

Francesco
 
F

Francesco

Also changing this:
    Color col(Color::color(i));
to this (adding the parentheses):
    Color col((Color::color(i)));
solves the problem.

Hence this must me a parsing problem, but I don't see how:
    Color col(Color::color(i));
could be considered a function declaration.

So, what's the issue here?

My brain, I suppose... never mind.

Freakin' parentheses, I've got it finally :-/

Cheers,
Francesco
 
J

Juha Nieminen

Francesco said:
Color col(Color::color(i));

The problem is that that line is not doing what you think it's doing.
You think it's creating an instance of the class Color named 'col'. In
reality you are declaring a function named 'col'.

Yes, this is an oddity in C++, probably some semantical leftover
from C. Extra parentheses will disambiguate the expression to mean what
you want it to mean.
 
F

Francesco

  The problem is that that line is not doing what you think it's doing.
You think it's creating an instance of the class Color named 'col'. In
reality you are declaring a function named 'col'.

  Yes, this is an oddity in C++, probably some semantical leftover
from C. Extra parentheses will disambiguate the expression to mean what
you want it to mean.

Thank you for your reply Juha, yes, finally I've got this straight -
that's what I meant with "Freakin' parentheses" ;-)

Actually, I knew this issue but I didn't recognize it - as you might
guess, I thought the compiler was broken ;-) - now that I hit this
obstacle in my actual code (that's the first time), chances are I'll
recognize it the next time - fingers crossed :-/

Best regards,
Francesco
 
J

Jerry Coffin

Thank you for your reply Juha, yes, finally I've got this straight -
that's what I meant with "Freakin' parentheses" ;-)

Actually, I knew this issue but I didn't recognize it - as you might
guess, I thought the compiler was broken ;-) - now that I hit this
obstacle in my actual code (that's the first time), chances are I'll
recognize it the next time - fingers crossed :-/

Unfortunately, chances are that it'll still bite you, at least once
in a while. One obvious one is if you have something like this:

std::copy(std::istream_iterator(std::cin),
std::istream_iterator(),
std::back_inserter(my_vector));

Now, this works, but it's quite long, so you might want to break it
up into some pieces that are more readable, like this:

std::istream_iterator input(std::cin);
std::istream_iterator end();

std::copy(input, end, std::back_inserter(my_vector));

There's just one minor problem: even though you did essentially the
same thing to define 'input' and 'end', end isn't really a definition
at all -- since the parens are empty, it's really a declaration of a
function named end that returns a std::istream_iterator and takes no
parameters.
 
F

Francesco

Unfortunately, chances are that it'll still bite you, at least once
in a while. One obvious one is if you have something like this:

std::copy(std::istream_iterator(std::cin),
        std::istream_iterator(),
        std::back_inserter(my_vector));

Now, this works, but it's quite long, so you might want to break it
up into some pieces that are more readable, like this:

std::istream_iterator input(std::cin);
std::istream_iterator end();

std::copy(input, end, std::back_inserter(my_vector));

There's just one minor problem: even though you did essentially the
same thing to define 'input' and 'end', end isn't really a definition
at all -- since the parens are empty, it's really a declaration of a
function named end that returns a std::istream_iterator and takes no
parameters.

I'll watch out for strange errors like the one I've got for my code
(i.e. something that should be a class isn't recognized as such) and
I'll double check the declarations, thanks for pointing out this
further example Jerry.

All the best,
Francesco
 
J

James Kanze

Unfortunately, chances are that it'll still bite you, at least
once in a while.

It still bites me from time to time, and that's after twenty
years experience with C++.
One obvious one is if you have something like this:

Now, this works, but it's quite long, so you might want to break it
up into some pieces that are more readable, like this:
std::istream_iterator input(std::cin);
std::istream_iterator end();
std::copy(input, end, std::back_inserter(my_vector));
There's just one minor problem: even though you did
essentially the same thing to define 'input' and 'end', end
isn't really a definition at all -- since the parens are
empty, it's really a declaration of a function named end that
returns a std::istream_iterator and takes no parameters.

The case I run into the most is when I want to initialize the
array directly, instead of using copy:

std::vector< int > my_vector(
std::istream_iterator< int >( std::cin ),
std::istream_iterator< int >() ) ;

Stupid compiler doesn't realize that if I'm naming it
"my_vector", then I don't want a function. (And I use this
idiom a lot, since if I'm not modifying the vector later, it
allows me to declare it const.)
 
F

Francesco

It still bites me from time to time, and that's after twenty
years experience with C++.


The case I run into the most is when I want to initialize the
array directly, instead of using copy:

    std::vector< int > my_vector(
        std::istream_iterator< int >( std::cin ),
        std::istream_iterator< int >() ) ;

Stupid compiler doesn't realize that if I'm naming it
"my_vector", then I don't want a function.  (And I use this
idiom a lot, since if I'm not modifying the vector later, it
allows me to declare it const.)

Sorry for replying to a post which wasn't addressed to me, James, but
the code you posted above compiles and runs fine (it creates a vector
instead of declaring a function) - at least on my environment. Is it
really expected to rise the parsing problem?

Francesco
 
V

Victor Bazarov

Francesco said:
[..]
The case I run into the most is when I want to initialize the
array directly, instead of using copy: ^^^^^^^

std::vector< int > my_vector(
std::istream_iterator< int >( std::cin ),
std::istream_iterator< int >() ) ;

Stupid compiler doesn't realize that if I'm naming it
"my_vector", then I don't want a function. (And I use this
idiom a lot, since if I'm not modifying the vector later, it
allows me to declare it const.)

Sorry for replying to a post which wasn't addressed to me, James, but
the code you posted above compiles and runs fine (it creates a vector
instead of declaring a function) - at least on my environment.

What environment is that? And how do you know it creates a vector?
> Is it
really expected to rise the parsing problem?

Parsing problem? In what way? Try compiling this:

#include <vector>
#include <iostream>
#include <iterator>
#include <istream>

int main()
{
std::vector< int > my_vector(
std::istream_iterator< int >( std::cin ),
std::istream_iterator< int >() ) ;

my_vector.size();
}

It's not the declaration of 'my_vector' itself that doesn't compile.
The declaration is not of an object, though. The compiler will choke
when I try using the dot operator to call the 'size' member function of
'std::vector'. And the reason is simple: 'my_vector' is not an object
but a function.

V
 
F

Francesco

Francesco said:
[..]
The case I run into the most is when I want to initialize the
array directly, instead of using copy:

                    ^^^^^^^


Sorry for replying to a post which wasn't addressed to me, James, but
the code you posted above compiles and runs fine (it creates a vector
instead of declaring a function) - at least on my environment.

What environment is that?  And how do you know it creates a vector?

 > Is it
really expected to rise the parsing problem?

Parsing problem?  In what way?  Try compiling this:

#include <vector>
#include <iostream>
#include <iterator>
#include <istream>

int main()
{
     std::vector< int > my_vector(
         std::istream_iterator< int >( std::cin ),
         std::istream_iterator< int >() ) ;

     my_vector.size();

}

It's not the declaration of 'my_vector' itself that doesn't compile.
The declaration is not of an object, though.  The compiler will choke
when I try using the dot operator to call the 'size' member function of
'std::vector'.  And the reason is simple: 'my_vector' is not an object
but a function.

Victor, I'm taking on the habit to test the code before making my
assertions. I believe you didn't test your code, because no compiler
should accept declaring a parameter function called "std::cin". In
fact, it doesn't interpret that as a function declaration but as a
vector instantiation. Try that yourself.

Francesco
 
V

Victor Bazarov

Francesco said:
Francesco said:
[..]
The case I run into the most is when I want to initialize the
array directly, instead of using copy: ^^^^^^^



std::vector< int > my_vector(
std::istream_iterator< int >( std::cin ),
std::istream_iterator< int >() ) ;
Stupid compiler doesn't realize that if I'm naming it
"my_vector", then I don't want a function. (And I use this
idiom a lot, since if I'm not modifying the vector later, it
allows me to declare it const.)
Sorry for replying to a post which wasn't addressed to me, James, but
the code you posted above compiles and runs fine (it creates a vector
instead of declaring a function) - at least on my environment.
What environment is that? And how do you know it creates a vector?
really expected to rise the parsing problem?
Parsing problem? In what way? Try compiling this:

#include <vector>
#include <iostream>
#include <iterator>
#include <istream>

int main()
{
std::vector< int > my_vector(
std::istream_iterator< int >( std::cin ),
std::istream_iterator< int >() ) ;

my_vector.size();

}

It's not the declaration of 'my_vector' itself that doesn't compile.
The declaration is not of an object, though. The compiler will choke
when I try using the dot operator to call the 'size' member function of
'std::vector'. And the reason is simple: 'my_vector' is not an object
but a function.

Victor, I'm taking on the habit to test the code before making my
assertions. I believe you didn't test your code, because no compiler
should accept declaring a parameter function called "std::cin". In
fact, it doesn't interpret that as a function declaration but as a
vector instantiation. Try that yourself.

You are correct, of course. My mistake. I did check with Comeau, and
it must have pointed that out, but I just concentrated on the second
error message and not the first.

Most likely the code isn't supposed to contain 'std::', and that must
have been the intention when James posted his snippet. Not an excuse
for my missing the first error message, just an observation.

V
 
F

Francesco

Francesco said:
Francesco wrote:
[..]
The case I run into the most is when I want to initialize the
array directly, instead of using copy:
                    ^^^^^^^
    std::vector< int > my_vector(
        std::istream_iterator< int >( std::cin ),
        std::istream_iterator< int >() ) ;
Stupid compiler doesn't realize that if I'm naming it
"my_vector", then I don't want a function.  (And I use this
idiom a lot, since if I'm not modifying the vector later, it
allows me to declare it const.)
Sorry for replying to a post which wasn't addressed to me, James, but
the code you posted above compiles and runs fine (it creates a vector
instead of declaring a function) - at least on my environment.
What environment is that?  And how do you know it creates a vector?
 > Is it
really expected to rise the parsing problem?
Parsing problem?  In what way?  Try compiling this:
#include <vector>
#include <iostream>
#include <iterator>
#include <istream>
int main()
{
     std::vector< int > my_vector(
         std::istream_iterator< int >( std::cin ),
         std::istream_iterator< int >() ) ;
     my_vector.size();
}
It's not the declaration of 'my_vector' itself that doesn't compile.
The declaration is not of an object, though.  The compiler will choke
when I try using the dot operator to call the 'size' member function of
'std::vector'.  And the reason is simple: 'my_vector' is not an object
but a function.
Victor, I'm taking on the habit to test the code before making my
assertions. I believe you didn't test your code, because no compiler
should accept declaring a parameter function called "std::cin". In
fact, it doesn't interpret that as a function declaration but as a
vector instantiation. Try that yourself.

You are correct, of course.  My mistake.  I did check with Comeau, and
it must have pointed that out, but I just concentrated on the second
error message and not the first.

No problem. Good Lord's Compiler always chocked on "Human::perfect",
and usually "Faulty.front() == me".
Most likely the code isn't supposed to contain 'std::', and that must
have been the intention when James posted his snippet.  Not an excuse
for my missing the first error message, just an observation.

Now that you made me think about it, of course James meant that. It
was easy to guess, after all.
Mistakes. They happen.

Best regards,
Francesco
 
J

James Kanze

Sorry for replying to a post which wasn't addressed to me,
James, but the code you posted above compiles and runs fine
(it creates a vector instead of declaring a function) - at
least on my environment. Is it really expected to rise the
parsing problem?

Oops. I simplified it a little too much for posting. The
problem only occurs if you have an unqualified variable name
instead of std::cin, e.g.:

std::ifstream input( filename ) ;
std::vector< int > my_vector(
std::istream_iterator< int >( input ),
std::istream_iterator< int >() ) ;

Note that you won't get a compiler error until you try to use
my_vector as a vector; both of the above statements are
definitely legal C++, it's just that the second means something
different than what was wanted.
 
J

James Kanze

You are correct, of course. My mistake. I did check with
Comeau, and it must have pointed that out, but I just
concentrated on the second error message and not the first.
Most likely the code isn't supposed to contain 'std::', and
that must have been the intention when James posted his
snippet.

Not quite. The code was extracted from real cases where I've
had the problem, and in real code (as opposed to snippets just
written to test a point here), I never read from std::cin, I
read from an std::istream&. Which may have been initialized
with std::cin, of course, but doesn't have a qualified name
(since 9 times out of ten, it's a function argument). Rather
than post a snippet with extra variables or functions, etc., I
"simplified" it to use std::cin. (And since I never write cin
without the qualifier, I ended up with a qualified name, which
causes the code to work as expected. And introduces perhaps yet
another way to disambiguate---except that most of the time, the
symbol is either a local variable or a parameter, so can't be
qualified.)
 

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,769
Messages
2,569,582
Members
45,062
Latest member
OrderKetozenseACV

Latest Threads

Top