C++ has a nice new feature:
struct Point{
int x;
int y;
int z;
};
Point p{.x=47, .y=1701, .z=0};
But if I add a constructor then I am forbidden from using the nice designated initalizers syntax:
struct Point{
Point(int x, int y, int z = 0): x(x), y(y), z(z){}
int x;
int y;
int z;
};
static Point p{.x=47, .y=1701, .z = 0};
error: designated initializers cannot be used with a non-aggregate type 'Point'
Am I missing something obvious(why it would be terrible if designated initalizers worked with structs/classes that have public members, but are not aggregates) or this is just a missing feature that is just not added to the standard?
Aggregate initialization (including initialization with designed initializers) circumvents the constructor of the class.
This is not a problem for aggregates, since they aren't allowed to have user-defined constructors. But if you allow this kind of initialization for classes with user-provided constructors (that do something useful), it can be harmful.
Consider this example:
class A
{
static std::map<A *, int> &Indices()
{
static std::map<A *, int> ret;
return ret;
}
public:
int dummy = 0;
A(int index)
{
Indices().emplace(this, index);
}
A(const A &) = delete;
A &operator=(const A &) = delete;
~A()
{
auto it = Indices().find(this);
std::cout << "Deleting #" << it->second << '\n';
Indices().erase(it);
}
};
If you were able to do A{.dummy = 42};
, you'd get UB in the destructor, and would have no way to protect against this kind of usage.