What's the difference between doing
A a{ A() };
and,
A a( A{} );
to avoid the Most Vexing Parse? When should I use a particular one?
What's the difference between doing
A a{ A() };
and,
A a( A{} );
to avoid the Most Vexing Parse? When should I use a particular one?
The two syntaxes are equivalent in most situations, and which one to choose is mostly a matter of taste. If you are into uniform initialization, I would suggest doing:
A a{ A{} };
Otherwise, parentheses alone can be used to disambiguate:
A a((A())); // This can't be parsed as a function declaration
Notice, that there is one situation (very unlikely, I must say) where the two forms shown in your question are not equivalent. If your class A
has a constructor that takes an initializer_list<A>
, that constructor will be favored over the copy constructor when the braces are used:
#include <initializer_list>
#include <iostream>
struct A
{
A() { }
A(std::initializer_list<A> l) { std::cout << "init-list" << std::endl; }
A(A const& a) { std::cout << "copy-ctor" << std::endl; }
};
int main()
{
A a(A{}); // Prints "copy-ctor" (or nothing, if copy elision is performed)
A b{A()}; // Prints "init-list"
}
The above difference is shown in this live example.
In most situations they are equivalent, but A a{ A() };
will prefer a std::initializer_list
constructor if one is present, while A a( A{} );
will prefer a move/copy constructor.
When the construct ends up calling a move/copy constructor, the construction of the new object can be elided, but this is not possible for a std::initializer_list
constructor.
Neither syntax will ever be parsed as a function declaration, so both avoid the most-vexing-parse.
#include <iostream>
#include <initializer_list>
struct A {
A() {
std::cout << "A()\n";
}
A(A&&) {
std::cout << "A(A&&)\n";
}
A(std::initializer_list<A>) {
std::cout << "A(std::initializer_list<A>)\n";
}
};
int main()
{
{A a{ A() };} // Prints "A()\n" "A(std::initializer_list<A>)\n"
{A a( A{} );} // Prints "A()\n" and *possibly*
// (depending on copy elision) "A(A&&)\n"
}