[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Bug#116875: g++-3.0: nested type converter in initializer confuses gcc



>    non-aggregate type `Foo ()(int (*)())'
> 	// This is the problematic line:
> 	Foo broken(int(returnLong()));
[...]
> The error message from g++ is: 
> gcc-bug-constructor.cc:36: request for member `field' in `broken', which is of 
>    non-aggregate type `Foo ()(int (*)())'

Thanks for your bug report. This is not a bug in the compiler, but in
your code. In C++, it is allowed to put parentheses into declarations
in order to group them better, and it is allowed to leave out the
"extern" keyword for function declarations. Furthermore, the type
"function" decays to "pointer to function" in a signature. So your
"broken" declaration is equivalent to

   Foo broken(int (returnLong)());

which in turn is equivalent to

   Foo broken(int (*returnLong)());  // decaying the function type

which in turn is equivalent to

   extern Foo broken(int (*returnLong)());

which is equivalent to

   extern Foo broken(int (*)());

So "broken" is the declaration of an external function (expecting a
function pointer, returning Foo), not of an object (of type Foo,
constructed with an expression).

There is an ambiguity in the C++ language, and 8.2, [dcl.ambig.res]/1
resolves it in favour of function declarations:

# The ambiguity arising from the similarity between a function-style
# cast and a declaration mentioned in 6.8 can also occur in the
# context of a declaration. In that context, the choice is between a
# function declaration with a redundant set of parentheses around a
# parameter name and an object declaration with a function-style cast
# as the initializer. Just as for the ambiguities mentioned in 6.8,
# the resolution is to consider any construct that could possibly be
# a declaration a declaration. [Note: a declaration can be explicitly
# disam-biguated by a nonfunction-style cast, by a = to indicate
# initialization or by removing the redundant parentheses around the
# parameter name. ]

Notice that the standard explicitly recommend to avoid function-style
casts in such cases, e.g. in favour of the static_cast that you've
used for the "alsoWorks" case.

HTH,
Martin



Reply to: