with initialize argument c++ c++11 initializer-list

c++ - initialize - Constructor de listas de inicializadores incluidos



c++ initializer list (3)

Debe usar el tipo de plantilla std :: initializer_list. Ejemplo:

#include <iostream> class X { public: X (std::initializer_list<int> list) { for (auto i = list.begin(); i != list.end(); i++) { std::cout << *i << std::endl; } } }; int main () { X x = {1,2,3,4,5}; }

Tengo un fenotipo de clase con el siguiente constructor:

Phenotype(uint8 init[NUM_ITEMS]);

Puedo crear un fenotipo como este:

uint8 data[] = {0,0,0,0,0}; Phenotype p(data);

Pero me sale un error cuando intento crear uno como este:

Phenotype p = {0,0,0,0,0};

Salida:

$ make g++ -Wall -g main.cpp -std=c++0x main.cpp: In function ‘int main(int, char**)’: main.cpp:109: error: no matching function for call to ‘Phenotype::Phenotype(<brace-enclosed initializer list>)’ main.cpp:37: note: candidates are: Phenotype::Phenotype(uint8*)

El error parece indicar que hay una manera de definir un constructor que toma una lista de inicializadores incluidos en llaves. ¿Alguien sabe cómo se podría hacer esto?


En C ++ 0x parece que puedes crear un constructor para esto. No tengo experiencia con esto, pero parece que se llama inicializador list-constructor .

Un contenedor puede implementar un constructor de listas de inicialización como este:

template<class E> class vector { public: vector (std::initializer_list<E> s) // initializer-list constructor { reserve(s.size()); // get the right amount of space uninitialized_copy(s.begin(), s.end(), elem); // initialize elements (in elem[0:s.size())) sz = s.size(); // set vector size } // ... as before ... };


Solo se puede hacer para agregados (matrices y ciertas clases. Contrariamente a la creencia popular, esto también funciona para muchos nopod). Escribir un constructor que los tome no es posible.

Dado que lo etiquetó como "C ++ 0x", entonces esto es posible. Las palabras mágicas son "constructor inicializador-lista". Esto es como

Phenotype(std::initializer_list<uint8> c) { assert(c.size() <= std::size(m_array)); std::copy(c.begin(), c.end(), m_array); } // used like Phenotype p1{1, 2, 3}; Phenotype p2({1, 3, 2}); // works too Phenotype p3(1, 2, 3); // doesn''t work

Sin embargo, dicha inicialización construirá la matriz por defecto y luego usará el operador de asignación. Si busca velocidad y seguridad (¡obtiene errores de tiempo de compilación para demasiados inicializadores!), También puede usar un constructor ordinario con una plantilla variadica.

Sin embargo, esto puede ser más genérico de lo necesario (a menudo una initializer_list es completamente suficiente, especialmente para enteros simples). Se beneficia de un reenvío perfecto, por lo que un argumento de valor razonable puede moverse construido en un elemento de matriz

template<typename ...T> Phenotype(T&&...t):m_array{ std::forward<T>(t)... } { } // used like Phenotype p1{1, 2, 3}; Phenotype p2(1, 2, 3); // works too Phenotype p3({1, 2, 3}); // doesn''t work

¡Es una elección difícil!

Corrección de edición , la última también funciona, ya que no hicimos que el constructor sea explicit , por lo que puede usar el constructor de copia de Phenotype , construir un objeto Phenotype temporal y copiarlo en p3 . Pero eso no es lo que realmente queremos que sean las llamadas :)