The issue here is that the compiler interprets the statement
test(_b);
not as code that creates a temporary object of type test
passing in parameter _b
, but as a variable declaration for a variable named _b
of type test
, using the default constructor. Consequently, what looks like a piece of code that creates a temporary test
object using the second constructor is instead recursively creating a new object of type test
and invoking the constructor another time.
To fix this, you can give the variable an explicit name, such as
test t(_b);
This can only be interpreted as a variable of type test
named t
, initialized using the second constructor.
I have never seen this before, and I’ve been programming in C++ for years. Thanks for showing me yet another corner case of the language!
For an official explanation: According to the C++03 ISO spec, ยง6.8:
There is an ambiguity in the grammar involving expression-statements and declarations: An expression-statement with a function-style explicit type conversion (5.2.3) as its leftmost subexpression can be indistinguishable from a declaration where the first declarator starts with a (. In those cases the statement is a declaration.
(My emphasis). In other words, any time C++ could interpret a statement as either an expression (the temporary object cast) or as a declaration (of a variable), it will pick the declaration. The C++ spec explicitly gives
T(a);
As an example of a declaration, not a cast of a
to something of type T
.
This is C++’s Most Vexing Parse – what looks like an expression is instead getting interpreted as a declaration. I’ve seen the MVP before, but I have never seen it in this context.