2012-04-16 13 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; 
} 

Mi sono preoccupato di come assegnare un oggetto __stdcall function a std::function. Ma senza alcuna convenzione di chiamata specifica, sembra funzionare bene. Come può std::function sapere quale convenzione di chiamata è?Come funziona la funzione std :: function sulla convenzione di chiamata?

+2

Allo stesso modo il compilatore sa come chiamare la funzione senza 'std :: function'. 'std :: function' usa type-erasure per creare una minuscola black-box interna che, quando chiamate la' std :: function', viene chiamata per eseguire la chiamata "reale", che il compilatore ha già capito. – GManNickG

risposta

6

std::function è in grado di memorizzare i puntatori di funzione che utilizzano qualsiasi convenzione di chiamata.

§ 20.8.11.2: template class

La funzione fornisce wrapper polimorfici che generalizzano il concetto di un puntatore a funzione. I wrapper possono memorizzare, copiare e chiamare oggetti callable arbitrari (20.8.1), dato una firma di chiamata (20.8.1), consentendo alle funzioni di essere oggetti di prima classe.

Come John Calsbeekadded: Non c'è nulla in particolare nella norma riguardante le convenzioni di chiamata, ma i compilatori stanno facendo il loro lavoro e puntatori a funzione contiene le informazioni sulla convention.

Con puntatori a funzione si avrebbe bisogno di specificare la convenzione di chiamata insolita:

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

Non sono sicuro che sia tecnicamente una risposta, dal momento che lo standard C++ menziona a malapena la convenzione di chiamata, e certamente non qui. La risposta è che 'std :: function'" ricorda "il tipo della funzione usando la magia della cancellazione dei tipi, ei puntatori di funzione nei compilatori più ragionevoli contengono informazioni sulla convenzione di chiamata utilizzata. –

+0

@JohnCalsbeek: hai ragione, non c'è nulla di più dettagliato nello standard che menzionare la parte citata. Le convenzioni di chiamata sono un territorio inesplorato, ma i compilatori sono ben educati e fanno ciò che è necessario. – Anonymous

+2

La cosa più vicina è "C linkage". Lì il compilatore deve solo farlo funzionare - non c'è nulla nello standard che renda il programmatore responsabile. Per estensione, dal momento che lo standard non dice nulla sulla chiamata delle convenzioni, quel silenzio lo rende di nuovo una responsabilità per il compilatore. – MSalters

Problemi correlati