Search code examples
c++gccoperator-precedence

Evaluation order of elements in an initializer list


Why is function g() called first? I defined g() as the second element in the initializer list.

Is the following quote from the standard, relating to initializer-lists, relevant?

§8.5.4.4: Within the initializer-list of a braced-init-list, the initializer-clauses, including any that result from pack expansions (§14.5.3), are evaluated in the order in which they appear.

#include <iostream>
#include <vector>

int f() { std::cout << "f"; return 0;}
int g() { std::cout << "g"; return 0;}

void h(std::vector<int> v) {}

int main() {

   h({f(), g()});
}

Output:

gf

Solution

  • It seems to me that the quote is relevant (the compiler sees an initializer list):

    8.5/14,16:

    The initialization that occurs in the form

    T x = a;

    as well as in argument passing, function return, throwing an exception (15.1), handling an exception (15.3), and aggregate member initialization (8.5.1) is called copy-initialization.

    .

    .

    The semantics of initializers are as follows[...]: If the initializer is a braced-init-list, the object is list-initialized (8.5.4).

    (more details in std::initializer_list as function argument and Folds (ish) In C++11)

    Moreover any {}-list should be sequenced (the standard uses a very strong wording about this fact. See also http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1030).

    So it's probably a GCC bug (fixed after gcc v4.9.0).

    Indeed, trying various GCC version, I get:

    GCC      with --std=c++11   without (--std=c++98)
    4.7.3        fg                    gf  <-
    4.8.1        fg                    gf  <-
    4.8.2        fg                    gf  <-
    4.9.0        fg                    gf  <-
    4.9.2        fg                    fg
    5.1.0        fg                    fg
    5.2.0        fg                    fg
    6.1.0        fg                    fg
    

    Extended initializer lists are only available with C++11 but GCC compiles the code anyway (with a warning, e.g. see gcc -Wall -Wextra vs gcc -Wall -Wextra -std=c++11).