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,
s1
is declared befores2
inFoo
. Consequently, it will be initialized first.If you had done the opposite (i.e. define
s1
based 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):