Por que uma sintaxe de chaves duplas não foi preferida para construtores que usam std :: initializer_list

Inicialização uniforme é um recurso importante e útil do C ++ 11. No entanto, você não pode simplesmente usar{} em todos os lugares desde:

std::vector<int> a(10, 0);    // 10 elements of value zero
std::vector<int> b({10, 0});  // 2 elements of value 10 and 0 respectively
std::vector<int> c{10, 0};    // 2 elements of value 10 and 0 respectively
std::vector<int> d = {10, 0}; // 2 elements of value 10 and 0 respectively

auto e(0);    // deduced type is int
auto f = 0;   // deduced type is int
auto g{0};    // deduced type is std::initializer_list<int>
auto h = {0}; // deduced type is std::initializer_list<int>

Notar queinicialização agregada por exemplostd::arrays requer o uso de{{}}, parece-me que todo o problema comqual construtor de vetor será selecionado poderia ter sido evitado exigindo uma{{}} chamar construtores tomando umastd::initializer_list:

std::vector<int> i{10, 0};    // 10 elements of value zero
std::vector<int> j{{10, 0}};  // 2 elements of value 10 and 0 respectively
std::vector<int> k = {10, 0}; // 2 elements of value 10 and 0 respectively

auto l{0};    // deduced type is int
auto m{{0}};  // deduced type is std::initializer_list<int>
auto n = {0}; // deduced type is std::initializer_list<int>

Tenho certeza que isso foi discutido, então quais foram as razões contra isso? Uma cotação / link de uma proposta padrão é preferida como resposta.

Atualizar. - Há um ponto emN2532 que afirma:

(3) Os prováveis casos de ambiguidade desagradáveis ocorrem apenas para pequenas listas de inicializadores [...]

(5) Por que as regras de linguagem devem forçar os programadores que desejam o controle da dispersão e da ambiguidade (por razões perfeitamente boas) a escrever mais para agradar aos programadores que preferem (por razões perfeitamente boas) serem mais explícitos - e podem ser?

[...]

Suponha que um programador espere que f (X) seja chamado. Como um f (Y) pode "seqüestrar" uma chamada?

(4) Suponha que X não tenha um construtor de lista de inicializadores, mas Y sim. Nesse caso, a prioridade dada aos construtores da lista de inicializadores favorece o seqüestrador (lembre-se de que assumimos que o programador de alguma forma esperava que f (X) fosse chamado). Isso é análogo a alguém que espera que f (y) invoque f (X) usando uma conversão definida pelo usuário e alguém vem com um f (Y) que corresponde exatamente.Eu acho que seria justo esperar que alguém que use {…} se lembre da possibilidade de construtores de listas de inicializadores. [ênfase minha]

Eu acho que a chave está nopode ser, o que significa que você não precisa usar a inicialização uniforme. Usando{} corretamente é difícil, pois:

você não apenas precisa verificar o construtor que deseja chamar, mas também oqualquer construtor tomando uminitializer_list que pode vencer (e provavelmente vencerá);

se você escrever código usando{} e alguém no futuro adiciona umstd::initializer_list construtor seu código pode quebrar e fazê-losilenciosamente.

Mesmo se você tiver uma aulaA com os construtoresA(int, bool) eA(std::initializer_list<double>), o último será selecionado sobre o primeiro paraA a{0, false}; (que IMO é louco), então achorealmente difícil usar a inicialização uniforme em classes que têm oupoderia possuem (são necessárias superpotências de bola de cristal)initializer_list construtores.

O fato de seu código poder quebrar silenciosamente me preocupa muito.

questionAnswers(2)

yourAnswerToTheQuestion