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.