2012-04-16 14 views
9
int __cdecl ccall(int i) 
{ 
    wprintf(L"ccall(%d)", i); 
    return 0; 
} 

int __stdcall stdcall(int i) 
{ 
    wprintf(L"stdcall(%d)", i); 
    return 0; 
} 

int __cdecl wmain(int argc, wchar_t **argv) 
{ 
    std::function<int(int)> fnc = ccall; 
    std::function<int(int)> fnstd = stdcall; 

    fnc(10); // printed well 
    fnstd(100); // printed well 
    return 0; 
} 

Ich war besorgt, wie ich eine __stdcall function zu std::function Objekt zuweisen. Aber ohne irgendwelche Aufruf Konvention, es sieht aus wie gut funktioniert. Wie kann std::function wissen, welche Aufrufkonvention ist?Wie kennt die std :: function die Aufrufkonvention?

+2

In gleicher Weise wird der Compiler weiß, wie die Funktion aufrufen, ohne 'std :: function'. 'std :: function' verwendet type-errasure, um eine kleine interne Black-Box zu erzeugen, die, wenn Sie die' std :: function aufrufen, aufgefordert wird, den "echten" Aufruf auszuführen, den der Compiler bereits herausgefunden hat. – GManNickG

Antwort

6

std::function kann Funktionszeiger speichern, die eine Aufrufkonvention verwenden.

§ 20.8.11.2:

Die Funktion Klassenvorlage bietet polymorphen Wrapper, die den Begriff der Funktionszeiger verallgemeinern. Wrapper können willkürlich aufrufbare Objekte (20.8.1) mit einer Signatur (20.8.1) speichern, kopieren und aufrufen, wodurch Funktionen zu Objekten erster Klasse werden.

Als John Calsbeekadded: Es gibt nichts, vor allem in der Norm in Bezug auf den Aufrufkonventionen, aber die Compiler tun ihre Arbeit und Funktionszeiger die Informationen über die Konvention enthalten.

Mit Funktionszeigern Sie benötigen würde die ungewöhnliche Aufrufkonvention zu spezifizieren:

typedef int(* c_ptr_t)(int); 
typedef int(__stdcall * std_ptr_t)(int); 

c_ptr_t c_ptr = ccall; 
std_ptr_t std_ptr = stdcall; 

// But std::function doesn't mind: 
std::function<int(int)> fnc = c_ptr; 
std::function<int(int)> fnstd = std_ptr; 
+5

Ich bin mir nicht sicher, dass das technisch eine Antwort ist, da der C++ - Standard kaum Aufrufkonventionen erwähnt, und es ist sicherlich nicht hier. Die Antwort ist, dass sich "std :: function" den Typ der Funktion mit der Magie des Typs löscht "merkt" und Funktionszeiger in den meisten sinnvollen Compilern Informationen über die verwendete Aufrufkonvention enthalten. –

+0

@ JohnCalsbeek: Sie haben Recht, es gibt nichts detaillierter in der Norm, als den zitierten Teil zu erwähnen. Die Aufrufkonventionen sind ein Neuland, aber Compiler verhalten sich gut und tun, was benötigt wird. – Anonymous

+2

Die nächste Sache ist "C-Verknüpfung". Da muss der Compiler nur funktionieren - es gibt nichts im Standard, das den Programmierer verantwortlich macht. Da der Standard nichts über das Aufrufen von Konventionen sagt, macht dieses Schweigen die Compiler-Verantwortlichkeit neu. – MSalters

Verwandte Themen