Consider the following code:
struct Foo{
std::string s1;
std::string s2;
};
int main(){
Foo f{.s1 = "s1", .s2 = f.s1 + "s2"};
std::cout << "s1='" << f.s1 << "', s2='" << f.s2 << "'" << std::endl;
}
Especially note that the initialization of s2 accesses the first member of f: .s2 = f.s1 + "s2".
The latest clang, gcc and MSVC are happy with the code and give the naively expected result (they print "s1='s1', s2='s1s2'"). See live on godbolt.
Question: Is this legal?
In other words, does the standard guarantee that f.s1 gets initialized before the designated initializer .s2 is evaluated?
Related: There is a similar question asking about whether .s2 = .s1 + "s2" is legal, which clearly isn't, because it does not compile. Also, P0328 (as per this answer) might be relevant, but I can't see my question being answered there.
In C++, the order is important. Member variables are initialized in order of declaration.
Initializer lists, designated or not, follow this rule.
In your case,
s1is declared befores2inFoo. Consequently, it will be initialized first.If you had done the opposite (i.e. define
s1based ons2) it would have beenill-formedUndefined Behaviour since you would have used a yet uninitialized member.From 9.4.5 List-initialization (§3.1):
Then from 9.4.2 Aggregates (§7):