please help understand this compilation error

Y

Yan

Here is the code:

class A {};

void (A::*A) (); // Line 3

int main() {
A a; // Line 6
return 0;
}

If you remove Line 3 everything becomes trivial and compiles. However
with line 3 present Line 6 doesn't compile (on VC++ 7.1) with the
following errors:
error C2146: syntax error : missing ';' before identifier 'a'
error C2065: 'a' : undeclared identifier

Line 3 declares a pointer to member by the name A. I guess it shadows
class A and that's why Line 6 doesn't compile. Why isn't the compiler
complaining about Line 3 instead (with let's say 'redifinition' error)?
I tried Cygwin version of gcc and it fails compiling and also points
out Line 6 as the source of the error.

Thank you for your comments.


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

Alf P. Steinbach

* Yan:
Here is the code:

class A {};

void (A::*A) (); // Line 3

int main() {
A a; // Line 6
return 0;
}

If you remove Line 3 everything becomes trivial and compiles. However
with line 3 present Line 6 doesn't compile (on VC++ 7.1) with the
following errors:
error C2146: syntax error : missing ';' before identifier 'a'
error C2065: 'a' : undeclared identifier

You may find it instructive to replace your line 3 with

int A;

which yields the same effect with less extranous clutter.

Line 3 declares a pointer to member by the name A. I guess it shadows
class A and that's why Line 6 doesn't compile. Why isn't the compiler
complaining about Line 3 instead (with let's say 'redifinition'
error)?

I don't know why, but the standard has examples of declaring a struct A
and some identifier A in the same namespace, and at least one rule for
disambiguation (3.4.3.2/5), so evidently it's allowed, in the same
spirit as overloading of functions.

That was news to me, because naturally I've never done that on purpose,
and (mystery) have never encountered it before in C++.

You can disambiguate in several ways; one way that seems to work is

int main()
{
class A a;
return 0;
}

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

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

Greg Herlihy

Yan said:
Here is the code:

class A {};

void (A::*A) (); // Line 3

int main() {
A a; // Line 6
return 0;
}

If you remove Line 3 everything becomes trivial and compiles. However
with line 3 present Line 6 doesn't compile (on VC++ 7.1) with the
following errors:
error C2146: syntax error : missing ';' before identifier 'a'
error C2065: 'a' : undeclared identifier

Line 3 declares a pointer to member by the name A. I guess it shadows
class A and that's why Line 6 doesn't compile. Why isn't the compiler
complaining about Line 3 instead (with let's say 'redifinition' error)?
I tried Cygwin version of gcc and it fails compiling and also points
out Line 6 as the source of the error.

The A member pointer name does not shadow the A class name, rather it
hides it. Change the A class name to B and the problem becomes more
clear:

class B {};

void (B::*A) (); // Line 3

int main()
{
A a; // Line 6

}

The A on line six is the name of a member pointer - not a class - so "A
a" is a syntax error. And because the two "A"'s are in distinct name
scopes (one is a class and the other an identifier), they do not
conflict - one simply ends up hiding the other.

Greg


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

Alf P. Steinbach

* Greg Herlihy:
The A member pointer name does not shadow the A class name, rather it
hides it. Change the A class name to B and the problem becomes more
clear:

class B {};

void (B::*A) (); // Line 3

int main()
{
A a; // Line 6

}

The A on line six is the name of a member pointer - not a class - so "A
a" is a syntax error. And because the two "A"'s are in distinct name
scopes (one is a class and the other an identifier), they do not
conflict - one simply ends up hiding the other.

Well, please, because I'm way too lazy to solve the puzzle, where does
the C++ standard define name scopes such as "class" and "identifier"?

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

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

Greg Herlihy

Alf said:
* Greg Herlihy:

Well, please, because I'm way too lazy to solve the puzzle, where does
the C++ standard define name scopes such as "class" and "identifier"?

I consulted the grammar summary in Appendix A and came up "class-name"
but no special term for a variable's name - only "identifier". A
class-name is also an identifier - so perhaps "name" or "variable name"
would been a better choice. Especially since §3.1/4 defines a "name"
as "a use of an identifier (2.10) that denotes an entity or label
(6.6.4, 6.1)." §3.1/2 defines "entity" as "a value, object, subobject,
base class subobject, array element, variable, function, instance of a
function, enumerator, type, class member, template, or namespace."

A name therefore is distinct from a user-declared "keyword" which can
be any of a "class-name, enum-name, template-name, typedef-name,
namespace-name, original-namespace-name or a namespace-alias."
(summarized in Appendix A.1)

The formal definition of naming hiding also distinguishes between
different name - here again I probably did not pick the best word to
use (scope) perhaps "category" or "type" - would have been more clear:

"A class name (9.1) or enumeration name (7.2) can be hidden by the name
of an object, function, or enumerator declared in the same scope. If a
class or enumeration name and an object, function, or enumerator are
declared in the same scope (in any order) with the same name, the class
or enumeration name is hidden wherever the object, function, or
enumerator name is visible." §3.3.7/2

Greg


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

kanze

Alf said:
You may find it instructive to replace your line 3 with
which yields the same effect with less extranous clutter.
I don't know why, but the standard has examples of declaring a
struct A and some identifier A in the same namespace, and at
least one rule for disambiguation (3.4.3.2/5), so evidently
it's allowed, in the same spirit as overloading of functions.

History. And C compatibility (in a way that is still very
important today). Basically, in C, structure names are in a
different namespace than other symbols, and something like:

struct A {} ;
int A ;

is perfectly legal. This causes no problems in C (and requires
no special rules) because you cannot use the first A as the name
of a type. You must write "struct A".

In C++, of course, after the first statement, A is the name of a
type, and can be used as such. And A is defined in the current
scope; logically, the second line would be illegal. However, if
you've got a C header which uses something like that, you still
want to be able to compile it in C++, by just wrapping the
header in ` extern "C" {...} '. So we get some very special,
and very strange rules, just to allow common headers for C and
C++.
That was news to me, because naturally I've never done that on
purpose, and (mystery) have never encountered it before in
C++.
You can disambiguate in several ways; one way that seems to work is
int main()
{
class A a;
return 0;
}

Right. The best solution, of course, is not to create the
ambiguity to begin with. If you're stuck with a C header which
has it, however, then the rule is that if there are two symbols,
one the name of a class, and one not, the one that is not the
name of a class is found except after the keywords class and
struct.

Personally, in such cases, I think I'd prefer using a typedef:

typedef class A AA ;

But it's arguable. If you're programming against a known API,
then struct A is presumably known to all of the programmers,
where as AA is an unknown type for them.

--
James Kanze GABI Software
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! ]
 
A

Alf P. Steinbach

* kanze:
Right. The best solution, of course, is not to create the
ambiguity to begin with. If you're stuck with a C header which
has it, however, then the rule is that if there are two symbols,
one the name of a class, and one not, the one that is not the
name of a class is found except after the keywords class and
struct.

Or perhaps 'enum', when the type is an enum type(but as stated earlier,
or at least as should have been stated earlier, I really don't feel like
finding the relevant small cryptic statements hidden in the standard).

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: 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

Forum statistics

Threads
473,764
Messages
2,569,566
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top