Constructor de lista de inicializador cerrado con llave
Tengo 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 recibo 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 forma de definir un constructor que toma una lista de inicializadores encerrada en llaves. ¿Alguien sabe cómo se puede hacer esto?
3 answers
Solo se puede hacer para agregados (arrays y ciertas clases. Contrariamente a la creencia popular, esto también funciona para muchos no ipod). Escribir un constructor que los tome no es posible.
Dado que lo etiquetaste como "C++0x", entonces esto es posible. Las palabras mágicas son "inicializador-constructor de lista". Esto va 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á por defecto la matriz y luego usará el operador de asignación. Si usted apunta para la velocidad y la seguridad (usted consigue compilar errores de tiempo para demasiados inicializadores!), también puede utilizar un constructor ordinario con una plantilla variadic.
Esto puede ser más genérico de lo necesario (a menudo una initializer_list es completamente suficiente, especialmente para enteros simples). Se beneficia del reenvío perfecto, de modo que un argumento rvalue se puede mover 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!
Editar Corrección, la última también funciona, ya que no hicimos el constructor explicit
, así que puede usar el constructor de copia de Phenotype
, construyendo un objeto temporal Phenotype
y copiarlo a p3
. Pero eso no es lo que realmente nos gustaría que fueran las llamadas:)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-04-08 16:59:46
En C++0x parece que se puede crear un constructor para esto. No tengo experiencia con él, pero parece que se llama initializer list-constructor.
Un contenedor podría implementar un constructor initializer-list 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 ...
};
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-11-07 14:05:47
Necesita 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};
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-11-07 14:13:15