2010-11-07 16 views
38

tengo fenotipo clase con el siguiente constructor:Brace-cerrado lista de inicialización del constructor

Phenotype(uint8 init[NUM_ITEMS]); 

puedo crear un fenotipo de esta manera:

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

Pero me da un error cuando trato de 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?

+0

posible duplicado de (http://stackoverflow.com/questions/3424727/can-we- pass-arrays-as-arguments-to-functions-by-this-syntax-under-upcoming-c0x) – kennytm

Respuesta

66

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", esto es posible. Las palabras mágicas son "constructor inicializador-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á 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.

Esto puede ser más genérico de lo necesario (sin embargo, una initializer_list es suficiente, especialmente para enteros simples). Se beneficia de reenvío perfecto, por lo 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 el constructor explicit, por lo que puede utilizar el constructor copia de Phenotype, la construcción de un objeto temporal Phenotype y copiarlo en p3. Pero eso no es lo que realmente queremos que sean las llamadas :)

+0

Muy útil. He estado buscando respuesta por un tiempo –

+2

Lo etiquetó como C++ 11. Pero ¿cómo es que no funciona en C++ 11? –

6

En C++ 0x parece que puedes crear un constructor para esto. No tengo experiencia con él, pero parece que se llama initializer list-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 ... 
}; 
3

Es necesario utilizar el std :: initializer_list tipo de plantilla. Ejemplo: [? Podemos pasar matrices como argumentos a las funciones de esta sintaxis, bajo próximo C++ normas 0x]

#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}; 
} 
Cuestiones relacionadas