By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,030 Members | 1,997 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,030 IT Pros & Developers. It's quick & easy.

please help understand this compilation error

P: n/a
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! ]

Mar 24 '06 #1
Share this Question
Share on Google+
6 Replies


P: n/a
* 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! ]

Mar 24 '06 #2

P: n/a
Yan wrote:
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! ]

Mar 25 '06 #3

P: n/a
* Greg Herlihy:
Yan wrote:
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.


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! ]

Mar 26 '06 #4

P: n/a
Alf P. Steinbach wrote:
* Greg Herlihy:
Yan wrote:
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.


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! ]

Mar 26 '06 #5

P: n/a
Alf P. Steinbach wrote:
* 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.
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! ]

Mar 27 '06 #6

P: n/a
* kanze:
Alf P. Steinbach wrote:
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.


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! ]

Mar 27 '06 #7

This discussion thread is closed

Replies have been disabled for this discussion.