2016-04-19 5 views
0

Ich bin mit einem ARM-Mikrocontroller und Compiler konvertieren, die C++ 11Warum bekomme ich diesen Fehler? Konnte nicht von <geschweiften Klammern stehenden Initialisiererliste> auf ‚std :: vector <>‘

ich eine Klasse wie folgt beschrieben unterstützt:

class commands 
{ 
public: 
    string cmd_str; 
    void (*fktPtr)(void); 
}; 

Das Diag Objekt ist Teil der Diag Klasse

class Diag 
{ 
public: 
void reset(void); 
} 

Diag diag; 

die Umschaltfunktion eine eigenständige Funktion im Code:

void toggle_pin(void); 

Dann habe ich einen Vektor von Befehlen definiert, die cmdlist genannt:

vector<commands> cmdlist = { 

{"togg",  toggle_pin }, // this works 
{"rst",  diag.reset}, // this gives an error. why ? 
{"rst1",  [](){diag.reset();}}, // this also works 
} 

Der Fehler:

main.cpp:81:1: error: could not convert '{{"togg", toggle_pin}, {"rst", diag.Diag::reset}}, {"rst1",<lambda closure object><lambda()>{}} from '<brace-enclosed initializer list>' to 'std::vector<commands>' 

Warum von einem Objekt nicht die Initialisiererliste Unterstützungsmethoden, unterstützt aber regelmäßige Funktionen/Lambda-Funktionen?

+0

Was sind "Befehle"? Vielleicht benötigen Sie einen Verweis auf die Methode wie & Diag :: Reset – CppChris

+3

1. Um eine Funktion aus einem Klassenbereich zugreifen, verwenden Sie '& Diag :: reset'-Syntax, 2.Eine nicht statische Elementfunktion kann nicht in einen Funktionszeiger umgewandelt werden –

+1

@Holt: Im angezeigten Code ist 'diag' global (Dateibereich) und der Lambda kann ohne Capture darauf zugreifen. –

Antwort

5

Es hat nichts mit der Initialisierung Listen oder Vektoren zu tun, werden Sie den gleichen Fehler aus

void (*fktPtr)(void) = diag.reset; 

Sie haben zwei Probleme bekommen können, ist ein, dass Sie die & fehlen einen Funktionszeiger zu erstellen. Es gibt eine implizite Umwandlung für bare Funktionen, um Zeiger zu funktionieren; Es gibt keine solche Konvertierung für Elementfunktionen.

Also dann haben wir:

void (*fktPtr1)(void) = &toggle_pin; // works 
void (*fktPtr2)(void) = &Diag::reset; // doesn't 

Jetzt haben Sie ein Problem inkompatibler Typen. Die Adresse einer nicht statischen Elementfunktion hat den Typ Zeiger auf Elementfunktion, im Gegensatz zu bare-Funktionen und statischen Elementfunktionen (diese benötigen noch explizite &ClassName::FunctionName, aber einen normalen Funktionszeiger). Sie können einen Zeiger-zu-Element nicht in einen normalen Funktionszeiger konvertieren.

Ein Teil des Problems besteht darin, dass die Zeiger-to-Elementfunktion ein Zielobjekt benötigt (manchmal this Parameter versteckt genannt). Die C++ - Methode, dies im Voraus zu setzen, ist mit std::bind, aber Sie erhalten immer noch keinen normalen Funktionszeiger.

Das Lambda ergibt eine gewöhnliche Funktion (der Zeiger endet in Ihrem Vektor), der das Zielobjekt von einer globalen Variablen abruft und eine Funktion darauf aufruft. Das ist legal, kann aber auch keine Klasse haben, da Sie an diese einzelne Instanz gebunden sind, die von der globalen Variable benannt wird.

Wenn Sie etwas näher an „Delegierten“ in Sprachen wie C# gefunden möchten, dass die Funktion und Ziel zusammen Objekt speichern, versuchen

std::function<void (void)> fktPtr; 

anstelle einer bloßen Funktionszeiger. Dies ist kompatibel mit blanken Funktionen, statischen Elementfunktionen, gebundenen Instanzelementfunktionen, nicht erfassenden Lambdas und dem Erfassen von Lambdas.

Verwandte Themen