While updating some of my C++98 code to C++11, I noticed uniform initialization is not so uniform. Some of them related to incomplete type like void
, while other are related to pod. e.g. For trivially copyable types, uniform initialization is not working for both direct initialization or copy initialization, when initialization involves copy/move constructor.
e.g.
template<class T>
T foo() { return T("Hello World");}
foo<void>();
foo<std::string>();
--------
template<class T>
T foo() { return T{"Hello World"};}
foo<void>();
foo<std::string>();
While the first part compiles, the second half fails with error: compound literal of non-object type 'void'
struct pod { int x;int y;};
pod p{1,2}; //ok pod p(1,2) is error as usual
pod p2(p);
struct foo
{
foo(foo const& rhs) : p_(rhs.p_){}
pod p_;
};
--------
struct pod { int x;int y;};
pod p{1,2};
pod p2{p};
struct foo
{
foo(foo const& rhs) : p_{rhs.p_}{}
pod p_;
};
Here also, the second half fails on copy construction with error: cannot convert 'pod' to 'int' in initialization
. Though I think, this pod
class is a trivial type (or even can be trivially copyable type) in c++11, but the problem remains same except primitive types
NOTE:
while the following works,
struct conv
{
operator int()const { return 1;}
};
pod p{1,2};
pod p2{conv{}};
This does not,
struct conv
{
operator pod()const { return pod{1,2};}
};
pod p{1,2};
pod p2{conv{}};
I also noticed C array does work with uniform initialization, but not with copy/move constructor. But that may be due to array being an aggregate which does not have copy/move constructor or assignment. Though I do not know why in c++11 those syntax are not allowed(specifically when they are class member, implicit copy/move does exactly that).
So, why can't I blindly change all C++98 initialization to C++11 style uniform initialization (Well , except for the types which has initializer list ! ) ?
I am using GCC 4.8.1