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
"Uniform initialization" is a non-standard term which was used somewhat unfortunately in promotion of the initializer-list feature during its proposal phase.
No, you can't use it everywhere. In my experience, it's best to restrict it to
initializer_list
)return
by value expressions calling a non-explicit constructorBlindly changing everything and expecting no semantic change is just argumentum ad novitatem — doing something because it's new and different, not because it's appropriate.
As for generic programming, yes it's hard to correctly support situations spanning the above categories. Post specific complaints to the message board at http://isocpp.org and perhaps the guys in charge of the language will work harder to restore the generic order which "uniform initialization" was supposed to improve, not aggravate :v) .
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With