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?

Author: Johannes Schaub - litb, 2010-11-07

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:)

 67
Author: Johannes Schaub - litb,
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 ...
};
 6
Author: Magnus Hoff,
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};
}
 3
Author: evnu,
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