Esse código com inicialização agregada é um programa C++ válido?
#include <iostream>
#include <numeric>
struct Sheet {
const int c[2]{};
const int sum = std::accumulate(std::begin(c), std::end(c), 0);
};
int main() {
Sheet sheet0;
Sheet sheet1{{10}};
Sheet sheet2{{10, 20}};
std::cout << sheet0.sum << "\n";
std::cout << sheet1.sum << "\n";
std::cout << sheet2.sum << "\n";
}
// Outputs:
// 0
// 10
// 30
Esta é uma estrutura com comportamento semelhante ao de uma planilha do Excel: um usuário inicializa células com alguns valores; se o usuário não inicializar, sum
ele obtém a soma computada dos valores das células.
Não tenho certeza se a inicialização de membros em linha, e não a inicialização zero, acontece em membros ignorados na inicialização agregada.
Eu esperava que a declaração
Sheet sheet2{{10, 20}};
seria o mesmo que
Sheet sheet2{{10, 20}, {}};
e saída 0, mas minhas execuções de programa mostraram que eles resultam em saídas diferentes 30 e 0.
Para
Sheet sheet2{{10, 20}};
, o membro de dadossum
será inicializado por seu inicializador de membro padrão. Não é o mesmo queSheet sheet2{{10, 20}, {}};
wheresum
será inicializado por{}
.Em detalhes, para
Sheet sheet0;
, o membro de dadosc
esum
será inicializado por seus inicializadores de membro padrão. Os 2 elementos dec
serão zero.Para
Sheet sheet1{{10}};
,c
será inicializado por{10}
,sum
será inicializado por seu inicializador de membro padrão. Como{10}
contém apenas 1 inicializador que é menor que o número de membros dec
como 2, o 1º elemento dec
será10
e o 2º será zero.Para
Sheet sheet2{{10, 20}};
,c
será inicializado por{10, 20}
,sum
será inicializado por seu inicializador de membro padrão. Como efeito, o 1º elemento dec
será10
e o 2º será20
.Não há nada de errado com o programa. O comportamento é bem definido e garantido que será o que você observa.
Se nenhum inicializador for fornecido para um elemento agregado na inicialização agregada, então ele é inicializado como se por a
= {}
menos que tenha um inicializador de membro padrão. De qualquer forma, elementos dec
que não têm um inicializador correspondente na inicialização agregada serão, portanto, inicializados para0
.sum
é declarado mais tarde do quec
na classe e sua inicialização é, portanto, sequenciada após a inicialização dec
. Como um inicializador de membro padrão é fornecido, esse será usado para inicializá-lo e, por causa do sequenciamento,c
já está inicializado e utilizável naquele ponto.