Ordem de avaliação dos elementos na boot da lista

No outro tópico , a @Dietmar deu esta solução:

template  std::tuple parse(std::istream& in) { return std::tuple{ T(in)... }; } 

declarando isso,

O uso da boot de chaveta funciona porque a ordem de avaliação dos argumentos em uma lista de inicializadores de chaves é a ordem em que eles aparecem . (enfatize o meu)

O texto relevante do C ++ Standard (n3485) é,

Dentro da lista de inicializadores de uma lista de boot apoiada, as cláusulas de boot, incluindo qualquer resultado de expansões de pacote (14.5.3), são avaliadas na ordem em que aparecem. Ou seja, todos os cálculos de valor e efeitos colaterais associados a uma determinada cláusula inicializadora são sequenciados antes de cada cálculo de valor e efeito colateral associado a qualquer cláusula inicializadora que a segue na lista separada por vírgula da lista de inicializadores. [Nota: Esta ordenação de avaliação é válida independentemente da semântica da boot; por exemplo, ele se aplica quando os elementos da lista de inicializadores são interpretados como argumentos de uma chamada de construtor, mesmo que normalmente não haja restrições de seqüência nos argumentos de uma chamada. – end note]


Então eu tentei testar isso com o seguinte código:

 template struct A { std::string data; A(std::istream & stream) { stream >> data; } friend std::ostream& operator<<(std::ostream & out, A const & a) { return out << "A"<<N<<"::data = " << a.data; } }; typedef A A1; typedef A A2; template void test(std::istream & stream) { std::tuple args { Args(stream)... }; std::cout << std::get(args) << std::endl; std::cout << std::get(args) << std::endl; } int main() { std::stringstream ss("A1 A2"); test(ss); } 

Produção esperada:

 A1::data = A1 A2::data = A2 

Saída real:

 A1::data = A2 A2::data = A1 

Eu fiz alguma coisa errada no meu código de teste? Eu mudei meu código para isso:

 std::stringstream ss("A1 A2"); std::tuple args{A1(ss), A2(ss)}; std::cout << std::get(args) << std::endl; std::cout << std::get(args) << std::endl 

Mesma saída de antes. Eu testei meu código com o MinGW (GCC) 4.7.0 e 4.7.2 . Até ideone dá essa saída .

É um bug no compilador?

Respondendo minha própria pergunta. Excluir a questão não seria uma boa ideia, pois alguém pode ter a mesma pergunta no futuro.

Sim. É um bug no compilador do GCC.

  • Bug 51253 – [C ++ 11] [DR 1030] Ordem de avaliação (relação sequenciada antes) entre cláusulas initializer em braced-init-list

retirado do comentário de @Johannes Schaub à pergunta.