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 returnsg
.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:
As for third:
When #1 and #2 are there, you've got a function declaration for
f
inmain
andg myG( ( f() ) );
is parsed as a declaration of an object of typeg
, namedmyG
and initialized with a result of a function call. You get a linker error because there's no definition forf
.When #1 and #2 are commented out, the type
f
is visible, and the disambiguation with parentheses kicks in:Without that pair, you'd get another function declaration.
What you want is this:
or something less Lisp-y:
static_cast<g>(f());