Su VC++ 2012, compilatore sceglie la conversione di chiamare automaticamente lambda apolidi (che non ha le variabili di acquisizione) quando si converte "lambda stateless a funzionare puntatore".
MSDN C++11 Features:
Lambda
[...] Inoltre in Visual C++ in Visual Studio 2012, lambda apolidi sono convertibili a funzionare puntatori. [...] (Il Visual C++ in Visual Studio 2012 è anche meglio di così, perché abbiamo reso lambda stateless convertibile a puntatori di funzioni che hanno convenzioni di chiamata arbitrarie.Questo è importante quando si utilizzano API che si aspettano cose come la funzione __stdcall
puntatori)
CURA:.
NB: La conversione chiamando è fuori di C++ standard, dipende da altre specifiche, come piattaforma di ABI (Application binary Interface).
Le seguenti risposte si basano sul codice dell'assieme di uscita con /FAs compiler option. Quindi è solo una supposizione, e per favore chiedete a Microsoft maggiori dettagli: P
Q1. Qual è la convenzione di chiamata di una funzione lambda C++?
Q3. Se la convenzione di chiamata non è definita, come riciclare correttamente lo spazio di stack dopo aver chiamato una funzione lambda?
Prima di tutto, C++ lambda (-expression) non è una funzione (né puntatore a funzione), è possibile chiamare operator()
per oggetto lambda come una normale funzione di chiamata. E il codice di assembly di output dice che VC++ 2012 genera lambda-body con la conversione di chiamate __thiscall
.
Q2. Come specificare la convenzione di chiamata di una funzione lambda C++?
AFAIK, non c'è modo. (Può essere solo __thiscall
)
Q4. Il compilatore genera automaticamente più versioni di una funzione lambda? cioè come il seguente pseudo-codice: [...]
Probabilmente No. Il VC++ 2012 lambda-tipo fornisce solo un'implementazione lambda-corpo (void operator()()
), ma fornisce più "conversione definita dall'utente funzionamento puntatore "per ogni conversione di chiamata (puntatore della funzione return dell'operatore con il tipo void (__fastcall*)(void)
, void (__stdcall*)(void)
e void (__cdecl*)(void)
).
Ecco un esempio;
// input source code
auto lm = [](){ /*lambda-body*/ };
// reversed C++ code from VC++2012 output assembly code
class lambda_UNIQUE_HASH {
void __thiscall operator()() {
/* lambda-body */
}
// user-defined conversions
typedef void (__fastcall * fp_fastcall_t)();
typedef void (__stdcall * fp_stdcall_t)();
typedef void (__cdecl * fp_cdecl_t)();
operator fp_fastcall_t() { ... }
operator fp_stdcall_t() { ... }
operator fp_cdecl_t() { ... }
};
lambda_UNIQUE_HASH lm;
Il collegamento a questa domanda sembra utile: http://stackoverflow.com/questions/14169295/how-to-specify-vc11-lambda-calling-convention – jogojapan
'f1' sta usando' __stdcall' ma 'h1' sta usando' __cdecl'; se scambi quelli intorno funziona? – congusbongus
@Cong, Gli errori sono normali e gli OK sono anormali. – xmllmx