This isn't a duplicate of Most vexing parse: why doesn't A a(()); work?, which is based on a parse in the form of A a(());
, whose OP thought would be able to default-construct an A
object using the extra set of parentheses.
In contrast, my question is about 2 classes, f
and g
, where f
has a default constructor and g
's ctor takes an f
. I want to call g
's ctor with a temporary f
argument, all without using uniform initialization syntax. There's a std::cout
statement in g
's ctor, so the lack of output signifies a function declaration instead of g
object instantiation. I annotated the sample code with 3 numbers in the comments. #1 and #2 were compiled with #3 commented out, and vice versa:
#include <iostream>
struct f {};
struct g {
g(f) { std::cout << "g's ctor\n"; }
};
int main() {
// -----Output-----
g( f() ); // #1: function declaration; expected
g( ( f() ) ); // #2: also a function declaration; UNEXPECTED
// g myG( ( f() ) ); // #3: "g's ctor" ONLY if #1 & #2 are commented out;
// ^ ... linker error otherwise
}
#1: I thought #1 declares an anonymous function that returns a g
and takes a pointer to a function that takes 0 arguments and returns an f
. Am I wrong?
#2: So, I thought the extra set of parentheses in #2 will force the enclosed contents to be evaluated as a function call, namely a call to f
's default ctor. But it's still a function declaration. Why?
#3: is a variant of #2, where the difference is #3's added instance name myG
. #3 instantiates the object if #1 and #2 are commented out. Otherwise I get these errors in VC12:
error LNK2019: unresolved external symbol "struct g __cdecl f(void)" (?f@@YA?AUg@@XZ) referenced in function _main
and
fatal error LNK1120: 1 unresolved externals
.
and this error in g++ 4.8: undefined reference to 'f()'
What do they mean, and why am I getting them?
Why is #3 an object instantiation only when the instance is named?
How can I get the desired instantiation effect without naming the instance or using uniform initialization?
The first one declares a function called f
that takes no parameters and returns g
.
g( f() );
// ^ ^ redundant set of parentheses
The second one is the same, with yet another redundant set of parentheses (remember that you can have as many declarations of the same functions as you wish). They are not always useless, though. You need them, say, to declare a function that returns a function pointer:
// function taking an int and returning
// a pointer to a function that takes a char
// and returns a g
g ( *f(int) )(char);
//^ ^ needed, syntax error without them
As for third:
When #1 and #2 are there, you've got a function declaration for f
in main
and g myG( ( f() ) );
is parsed as a declaration of an object of type g
, named myG
and initialized with a result of a function call. You get a linker error because there's no definition for f
.
When #1 and #2 are commented out, the type f
is visible, and the disambiguation with parentheses kicks in:
g myG( ( f() ) )
// ^ ^ these force an expression
Without that pair, you'd get another function declaration.
What you want is this:
( g(f()) );
// ^ ^ must be an expression as declarations can't be parenthesized
or something less Lisp-y: static_cast<g>(f());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With