To the best of my understanding, uniform initialization is the preferred syntax for initializing objects. Herb Sutter writes
For one thing, it’s called “uniform initialization” because it’s, well, uniform—the same for all types, including aggregate structs and arrays and std:: containers...
and the accepted answer to this question states
Prefer {} initialization over alternatives unless you have a strong reason not to.
However, consider this code:
#define BRACES
template<typename V>
class foo {
public:
template<typename W>
explicit foo(const W &w) :
#ifdef BRACES
m_v{w}
#else // #ifdef BRACES
m_v(w)
#endif // #ifdef BRACES
{}
private:
V m_v;
};
struct bar{};
int main()
{
bar b;
foo<bar>{b};
#ifdef BRACES
bar c{b};
#else // #ifdef BRACES
bar c(b);
#endif // #ifdef BRACES
}
If #define BRACES
is uncommented, this code fails to build (g++ 4.8.5) with error: too many initializers for ‘bar’
on the line
m_v{w}
in the constructor of foo
. This makes sense, as the more direct invocation
bar c{b};
in main
fails similarly, and they are essentially the same (although the template code does not know that).
Conversely, commenting #define BRACES
causes everything to build. Is this an indication to avoid this form of initialization in this type of template code?
Edit
@melak47 pointed out that this problem does not appear in g++5.1, and gave convincing proof. It apparently disappeared somewhere between 4.8.5 and 5.1.