c++language-lawyerc++20aggregate-initializationdesignated-initializer

Use of earlier member in designated initializer


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.


Solution

  • 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 before s2 in Foo. Consequently, it will be initialized first.

    If you had done the opposite (i.e. define s1 based on s2) it would have been ill-formed Undefined Behaviour since you would have used a yet uninitialized member.


    From 9.4.5 List-initialization (§3.1):

    If the braced-init-list contains a designated-initializer-list and T is not a reference type, T shall be an aggregate class. The ordered identifiers in the designators of the designated-initializer-list shall form a subsequence of the ordered identifiers in the direct non-static data members of T. Aggregate initialization is performed ([dcl.init.aggr]).

    Then from 9.4.2 Aggregates (§7):

    The initializations of the elements of the aggregate are evaluated in the element order. That is, all value computations and side effects associated with a given element are sequenced before those of any element that follows it in order.