You still don't need to syntactically require same order initialization, it's an easy job for a compiler to reorder things so that all dependencies work out - every language with order independent declarations have to do that for example.
You don't need to require same-order initialization, but allowing people to do different orders will be confusing when actions are reordered behind the scenes. Especially imagine if there are dependencies between the objects you're passing in.
struct A {
B one;
C two;
};
struct B {
B() {
cout << "init B" << endl;
}
}
struct C {
C() {
cout << "init C" << endl;
}
}
Mixing up the order is confusing:
A{.two=B(),.one=A()}
since `two` is initialized after `one` despite coming before (the comma operator <expr a>, <expr b> usually means `expr a` happens before `expr b`.
This case is a little contrived, but run the evolution forward: you can have members that depend on each other, or have complex initialization logic of their own. There, debugging the specific order of events is important.
In a general case you can't do that with separate compilation. [0]
struct A { A(A*); };
A* f(struct B *b);
struct B {
A a1;
A a2;
B(): a1(f(this)), a2(f(this)) {}
};
//in a different translation unit
A* f(B *b)
{
return &b->a1; //or a2, we don't know
}