Klammern eingeschlossener Initialisiererlistenkonstruktor

Ich habe class Phänotyp mit folgendem Konstruktor:

Phenotype(uint8 init[NUM_ITEMS]); 

Ich kann einen Phänotyp wie folgt erstellen:

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

Aber ich bekomme einen Fehler, wenn ich versuche, einen wie folgt zu erstellen:

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

Ausgabe:

 $ 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()' main.cpp:37: note: candidates are: Phenotype::Phenotype(uint8*) 

Der Fehler scheint anzuzeigen, dass es einen Weg gibt, einen Konstruktor zu definieren, der eine in Klammern eingeschlossene Initialisierungsliste verwendet. Weiß jemand, wie das gemacht werden könnte?

Es kann nur für Aggregate (Arrays und bestimmte classn) getan werden. Entgegen der landläufigen Meinung funktioniert dies auch für viele Nicht-PODs. Einen Konstruktor zu schreiben, der sie übernimmt, ist nicht möglich.

Da Sie es als “C ++ 0x” markiert haben, ist dies jedoch möglich. Die magischen Wörter sind “Initialisierungslisten-Konstruktor”. Das geht so

 Phenotype(std::initializer_list 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 

Eine solche Initialisierung erstellt jedoch standardmäßig das Array und verwendet dann den Zuweisungsoperator. Wenn Sie Geschwindigkeit und Sicherheit anstreben (Sie erhalten Kompilierungserrors für zu viele Initialisierer!), Können Sie auch einen gewöhnlichen Konstruktor mit einer variadischen Vorlage verwenden.

Dies kann generischer sein als nötig (oft ist eine initialiser_list vollständig ausreichend, insbesondere für einfache ganze Zahlen). Es profitiert von der perfekten Weiterleitung, so dass ein rvalue-Argument in ein Array-Element umgewandelt werden kann

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

Es ist eine schwere Entscheidung!

Edit Correction, das letzte funktioniert auch, da wir den Konstruktor nicht explicit , also kann er den Copy-Konstruktor von Phenotype benutzen, ein temporäres Phenotype Objekt konstruieren und es nach p3 kopieren. Aber das ist nicht, was wir wirklich wollen, dass die Anrufe sein 🙂

In C ++ 0x scheint es, dass Sie einen Konstruktor dafür erstellen können. Ich habe selbst keine Erfahrung damit, aber es sieht so aus, als würde es Initialisierungslisten-Konstruktor genannt .

Ein Container könnte einen Initialisierungslisten-Konstruktor wie folgt implementieren:

 template class vector { public: vector (std::initializer_list 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 ... }; 

Sie müssen den Vorlagentyp std :: initializer_list verwenden. Beispiel:

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