Brace-cerrado inicializador de constructor de la lista
-
29-09-2019 - |
Pregunta
Tengo clase fenotipo con el siguiente constructor:
Phenotype(uint8 init[NUM_ITEMS]);
Me puede crear un fenotipo de esta manera:
uint8 data[] = {0,0,0,0,0};
Phenotype p(data);
Pero me sale un error al intentar 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 tiene un aparato ortopédico-cerrado inicializador lista. ¿Alguien sabe cómo se puede hacer esto?
Solución
sólo se puede hacer para los agregados (arrays y ciertas clases. Contrariamente a la creencia popular, esto funciona para muchos nonpods también). Escribir un constructor que los lleva no es posible.
Desde que ha etiquetado como "C ++ 0x", entonces esto es posible sin embargo. Las palabras mágicas son "inicializador lista constructor". 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, tales inicialización por defecto construcción de la matriz y a continuación, utilizar el operador de asignación. Si tu objetivo para la velocidad y la seguridad (se producen errores en tiempo de compilación para demasiados inicializadores!), También se puede utilizar un constructor de ordinario con una plantilla de variadic.
Esto puede ser más genérico que necesitaba, aunque (a menudo una initializer_list basta por completo, especialmente para los enteros normales). Se beneficia de perfecto de reenvío, de modo que un argumento rvalue se puede mover hacia la construyó 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 decisión difícil!
Editar Corrección, el último que trabaja demasiado, ya que no hacemos la explicit
constructor, por lo que puede utilizar el constructor copia de Phenotype
, se construye un objeto Phenotype
temporal y copiarlo en p3
. Pero eso no es lo que realmente sería deseable que la llama a ser:)
Otros consejos
En C ++ 0x parece que se puede crear un constructor para esta. No tengo ninguna experiencia con él mismo, pero parece que se llama inicializador lista constructor .
Un contenedor podría implementar una inicialización del constructor-lista como esta:
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 ...
};
Se necesita usar la std :: initializer_list tipo de plantilla. 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};
}