14

Sagen wir, ich habe den folgenden Code:Kann ich die C++ 11-Klammerinitialisierungssyntax verwenden, um zu vermeiden, dass triviale Konstruktoren für einfache Aggregate deklariert werden?

#include <vector> 

struct Foo 
{ 
    int tag = 0; 
    std::function<void()> code; 
}; 

int main() 
{ 
    std::vector<Foo> v; 
} 

Und jetzt will ich mit dem spezifischen tag und codeohne explizit die Schaffung eines temporären ein neues Foo Artikel zum Vektor hinzuzufügen. Das bedeutet, dass ich einen Konstruktor für Foo hinzufügen:

struct Foo 
{ 
    inline Foo(int t, std::function<void()> c): tag(t), code(c) {} 

    int tag = 0; 
    std::function<void()> code; 
}; 

Und jetzt kann ich emplace_back:

v.emplace_back(0, [](){}); 

Aber wenn ich hatte dies wieder tun - zum 100. Mal - mit einer neu geschaffenen Struktur , Dachte ich: kann ich den Klammerinitialisierer nicht benutzen? Wie so:

#include <vector> 

struct Foo 
{ 
    int tag = 0; 
    std::function<void()> code; 
}; 

int main() 
{ 
    std::vector<Foo> v; 
    v.push_back(Foo{ 0, [](){} }); 
} 

, dass mir einen Übersetzungsfehler gibt (nicht konvertieren von ‚Initialisierer-Liste‘ auf ‚Foo‘), aber ich hoffe, dass dies getan werden kann, und ich habe gerade die Syntax falsch.

Antwort

14

In C++ 11, Sie können keine Aggregatinitialisierung mit Ihrem struct verwenden, weil Sie eine gleich initializer für das nicht-statische Element verwendet tag. Entfernen Sie den = 0 Teil und es wird funktionieren:

#include <vector> 
#include <functional> 

struct Foo 
{ 
    int tag; 
    std::function<void()> code; 
}; 

int main() 
{ 
    std::vector<Foo> v; 
    v.push_back(Foo{ 0, [](){} }); 
} 
+2

Beachten Sie diese Änderungen in C++ 14, wobei 'Foo' ein Aggregat ist und mithilfe der Aggregat-Initialisierung initialisiert werden kann. – chris

+1

Wow, das ist völlig unerwartet. Vielen Dank! –

+0

Danke @chris, jeden Tag lerne ich etwas Neues über C++ –

9

Gemäß dem Standard 11 C++ ist Foo nicht ein Aggregat, das Vorhandensein des Klammer-oder-gleich-Initialisierer es verhindert, dass ein Wesen.

jedoch this rule was changed for C++14, also, wenn Sie Ihren Code mit -std=c++14 (oder was auch immer Ihr Compiler entsprechende Einstellung ist) kompilieren, wird Foo ein Aggregat sein, und Ihr Code erfolgreich kompilieren.

Live demo

Für einen Compiler 11 ++ C, müssen Sie entweder die initializer entfernen, die Foo ein Aggregat machen wird, oder ein zwei Argument Konstruktor bieten.

+1

Ich warte auf Visual Studio 2015 für C++ 14 Unterstützung :) –