Mar 10, 2012

[c++11] initialization syntax trap

Uniform initialization syntax can be used with unions, but only the first member of the
union may be so initialized:
union u { int a; char* b; };
u a = { 1 }; // okay
u d = { 0, "asdf" }; // error
u e = { "asdf" }; // error (can’t initialize an int with a char array)




C++0x does not support C99’s designated initializers:
struct Point {
int x, y, z;
};
Point p { .x = 5, .z = 8 }; // error!

Sole exception: implicit narrowing.
 C++98 allows it via brace initialization, C++0x doesn’t:
struct Point { int x, y; };
Point p1 { 1, 2.5 }; // fine in C++98:
// implicit double ⇒ int
// conversion;
// error in C++0x
Point p2 { 1, static_cast <int>(2.5) }; // fine in both C++98
// and C++0x


The statement
v = { 0, 1, x, y };
creates no temporary vector for the assignment, because there’s a vector::operator= taking
a parameter of type std::initializer_list.



#include <initializer_list> // necessary header
std::u16string getName(int ID); // lookup name with given ID
class Widget {
public:
Widget(std::initializer_list<int> nameIDs)
{
names.reserve(nameIDs.size());
for (auto id: nameIDs) names.push_back(getName(id));
}
private:
std::vector<std::u16string> names;
};
...
Widget w { a[0]+a[1], x, 25, 16 }; // copies values into an array
// wrapped by an initializer_list
// passed to the Widget ctor.



When resolving constructor calls, std::initializer_list parameters are
preferred for brace-delimited arguments:
class Widget {
public:
Widget(double value, double uncertainty); // #1
Widget(std::initializer_list<double> values); // #2
…
};
double d1, d2;
…
Widget w1 { d1, d2 }; // calls #2
For brace-delimited arguments:
Widget w2(d1, d2); // calls #1


Initializer Lists and Overload Resolution
Given multiple std::initialization_list candidates, best match is
determined by worst element conversion:
class Widget {
public:
Widget(std::initializer_list<int>); // #1
Widget(std::initializer_list<double>); // #2
Widget(std::initializer_list<std::string>); // #3
Widget(int, int, int); // due to above ctors, this ctor not
}; // considered for “{... }” args
Widget w1 { 1, 2.0, 3 }; // int ⇒ double same rank as
// double ⇒ int, so ambiguous
Widget w2 { 1.0f, 2.0, 3.0 }; // float ⇒ double better than
// float ⇒ int, so calls #2
std::string s;
Widget w3 { s, "Init", "Lists" }; // calls #3

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.