c++ - principales - librerias turbo c
¿Qué ejemplos codiciosos de lista de inicializadores se esconden en la Biblioteca estándar? (2)
Solo buscando la ocurrencia de initializer_list
.
Todas las secuencias, tienen constructores como el de vector:
- deque
- dynarray
- forward_list
- lista
- vector
valarray
basic_string
Colecciones no ordenadas, hay un constructor que toma un número entero para determinar el conteo inicial del cubo.
- unordered_set
- unordered_multiset
Creo que eso es todo.
#include <unordered_set>
#include <iostream>
int main() {
std::unordered_set<int> f (3);
std::unordered_set<int> g {3};
std::cout << f.size() << "/" << g.size() << std::endl; // prints 0/1.
}
Desde C ++ 11, los contenedores de Standard Library y std::string
tienen constructores que toman una lista de inicializadores. Este constructor tiene prioridad sobre otros constructores (incluso, como lo señala @ JohannesSchaub-litb en los comentarios, incluso ignorando otros criterios de "mejor coincidencia"). Esto lleva a algunos errores conocidos al convertir todas las formas de constructores entre paréntesis ()
a sus versiones respaldadas {}
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
#include <string>
void print(std::vector<int> const& v)
{
std::copy(begin(v), end(v), std::ostream_iterator<int>(std::cout, ","));
std::cout << "/n";
}
void print(std::string const& s)
{
std::cout << s << "/n";
}
int main()
{
// well-known
print(std::vector<int>{ 11, 22 }); // 11, 22, not 11 copies of 22
print(std::vector<int>{ 11 }); // 11, not 11 copies of 0
// more surprising
print(std::string{ 65, ''C'' }); // AC, not 65 copies of ''C''
}
No pude encontrar el tercer ejemplo en este sitio, y el asunto surgió en el chat de Lounge <C ++> (en discusión con @rightfold, @Abyx y @JerryCoffin), lo más sorprendente es que la conversión de std::string
El constructor que toma un recuento y un caracter para usar {}
lugar de ()
, cambia su significado de n
copias del carácter al n
-ésimo carácter (generalmente de la tabla ASCII) seguido del otro carácter.
Esto no es atrapado por la prohibición usual de refuerzos para reducir las conversiones, porque 65 es una expresión constante que se puede representar como un carácter y conservará su valor original cuando se vuelva a convertir en int (§8.5.4 / 7, punto 4) (gracias a @JerryCoffin).
Pregunta : ¿hay más ejemplos al acecho en la Biblioteca estándar donde convertir un constructor de estilo ()
en {}
estilo, es avariciosamente igualado por un constructor lista de inicializadores?
Supongo que, con los ejemplos para std::vector<int>
y std::string
también se pretende cubrir los otros contenedores, por ejemplo, std::list<int>
, std::deque<int>
, etc. que tienen el mismo problema, obviamente, como std::vector<int>
. Del mismo modo, int
no es el único tipo, ya que también se aplica a char
, short
, long
y su versión unsigned
(posiblemente también algunos otros tipos integrales).
Creo que también hay std::valarray<T>
pero no estoy seguro de si se permite que T
sea de tipo integral. En realidad, creo que estos tienen una semántica diferente:
std::valarray<double>(0.0, 3);
std::valarray<double>{0.0, 3};
Hay algunas otras plantillas de clase de C ++ estándar que toman std::initializer_list<T>
como argumento, pero no creo que ninguno de estos tenga un constructor sobrecargado que se usaría al usar paréntesis en lugar de llaves.