From: 萌 朱 on
#include <iostream>
#include <typeinfo>
using namespace std;

typedef int T;
T a, (*(*b)(T))(T);

int main (int argc, char** argv)
{
typedef double T;
T(a), (*(*b(T)))(T);

cout << typeid(::a).name() << endl;
cout << typeid(a).name() << endl;

cout << typeid(::b).name() << endl;
cout << typeid(b).name() << endl;

return 0;
}

The above program is accepted by g++ but rejected by Comeau online and
MS VS.NET 2003. They all gave similar errors like this

"ComeauTest.c", line 11: error: declaration is incompatible with
previous "b"
(declared at line 6)
T(a), (*(*b(T)))(T);

I wonder is this a valid C++ program? I tend to think it is, anybody
can explain why this should be rejected? Thank you.

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

From: Yechezkel Mett on
On Dec 15, 2:31 am, 萌 朱 <rig...(a)gmail.com> wrote:

<snip/>

> The above program is accepted by g++ but rejected by Comeau online and
> MS VS.NET 2003. They all gave similar errors like this
>
> "ComeauTest.c", line 11: error: declaration is incompatible with
> previous "b"
> (declared at line 6)
> T(a), (*(*b(T)))(T);
>

You really don't need anything so complicated. The following
illustrates the point:

int b(); // line A

int main ()
{
double b(); // line B
}

And the point here is that line B is a function declaration. Functions
cannot be nested, and instead it is understood to be a declaration of
a function at namespace scope, exactly like line A. Since the two
declarations of b have different return types, you've violated the ODR
and the compiler complains.

Yechezkel Mett


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

From: Francis Glassborow on
? ? wrote:
> #include <iostream>
> #include <typeinfo>
> using namespace std;
>
> typedef int T;
> T a, (*(*b)(T))(T);
>
> int main (int argc, char** argv)
> {
> typedef double T;
> T(a), (*(*b(T)))(T);
Is this really what you wrote? Iwas expecting:
T a, (*(*b)(T))(T);
>
> cout << typeid(::a).name() << endl;
> cout << typeid(a).name() << endl;
>
> cout << typeid(::b).name() << endl;
> cout << typeid(b).name() << endl;
>
> return 0;
> }
>
> The above program is accepted by g++ but rejected by Comeau online and
> MS VS.NET 2003. They all gave similar errors like this
>
> "ComeauTest.c", line 11: error: declaration is incompatible with
> previous "b"
> (declared at line 6)
> T(a), (*(*b(T)))(T);
>
> I wonder is this a valid C++ program? I tend to think it is, anybody
> can explain why this should be rejected? Thank you.
>

If Comeau rejects it then you can be 99.99% certain that it isn't.
And writing declarations like that is sort of asking for trouble. But
before answering I need to know if the code you posted is actually the
code you gave to the compiler.


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

From: Johannes Schaub (litb) on
萌 朱 wrote:

> #include <iostream>
> #include <typeinfo>
> using namespace std;
>
> typedef int T;
> T a, (*(*b)(T))(T);
>
> int main (int argc, char** argv)
> {
> typedef double T;
> T(a), (*(*b(T)))(T);
>
> cout << typeid(::a).name() << endl;
> cout << typeid(a).name() << endl;
>
> cout << typeid(::b).name() << endl;
> cout << typeid(b).name() << endl;
>
> return 0;
> }
>

It declares "b" in global namespace declarative region as a function taking
an int and returning a pointer to such a function. And it declares "b" in
the block declarative region of main as a function taking int and returning
a pointer to a pointer to such a function. The function is a member of the
nearest enclosing namespace (3.5/7): "When a block scope declaration of an
entity with linkage is not found to refer to some other declaration, then
that entity is a member of the innermost enclosing namespace.". It also says
"However such a declaration does not introduce the member name in its
namespace scope.". This says that the name is not visible - i.e it is not
"in scope". It is still added to the declarative region of the namespace as
a not visible name.

It says however in 3.3/4: "Given a set of declarations in a single
declarative region, each of which specifies the same unqualified name, ...
they shall all refer to the same entity, or all refer to functions and
function templates; or [some case with classes hiding functions]" and
"[Note: these restrictions apply to the declarative region into which a name
is introduced, which is not necessarily the same as the region in which the
declaration occurs.]". In your case, one is the name of an object (function
pointer), and the other the name of a function.

The compilers erroring out on this are correct.

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

From: Seungbeom Kim on
Johannes Schaub (litb) wrote:
> 萌 朱 wrote:
>
>> #include <iostream>
>> #include <typeinfo>
>> using namespace std;
>>
>> typedef int T;
>> T a, (*(*b)(T))(T);
>>
>> int main (int argc, char** argv)
>> {
>> typedef double T;
>> T(a), (*(*b(T)))(T);
>>
[...]
>> }
>>
>
> It declares "b" in global namespace declarative region as a function taking
> an int and returning a pointer to such a function.

Not as a function, but as a pointer object, if the OP really wrote
what was meant.

> And it declares "b" in
> the block declarative region of main as a function taking int and returning
> a pointer to a pointer to such a function.

Isn't it as a function taking double?

> It says however in 3.3/4: "Given a set of declarations in a single
> declarative region, each of which specifies the same unqualified name, ...
> they shall all refer to the same entity, or all refer to functions and
> function templates; or [some case with classes hiding functions]" and
> "[Note: these restrictions apply to the declarative region into which a name
> is introduced, which is not necessarily the same as the region in which the
> declaration occurs.]". In your case, one is the name of an object (function
> pointer), and the other the name of a function.

Which entities are you referring to? The 'b' in the global namespace
scope and the other 'b' in the local scope defined by main()?
Do their declarations constitute "a set of declarations in a *single*
declarative region, each of which specifies the same unqualified name"
(emphasis mine)? If they are interpreted so, it would make name hiding
basically impossible, wouldn't it?

--
Seungbeom Kim

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