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

Me preocupaba cómo asignar un objeto __stdcall function a std::function. Pero sin ninguna convención de llamada específica, parece que funciona bien. ¿Cómo puede saber std::function qué es la convención de llamadas?¿Cómo sabe std :: function sobre las convenciones de llamadas?

+2

De la misma manera que el compilador sabe cómo llamar a la función sin 'std :: function'. 'std :: function' usa type-erasure para crear una pequeña caja negra interna que, cuando se llama a' std :: function' se le pide que realice la llamada "real", que el compilador ya ha descifrado. – GManNickG

Respuesta

6

std::function es capaz de almacenar indicadores de funciones que utilizan cualquier convención de llamadas.

§ 20.8.11.2: plantilla de clase

La función proporciona envoltorios polimórficos que generalizan la noción de un puntero de función. Los contenedores pueden almacenar, copiar y llamar objetos invocables arbitrarios (20.8.1), dada una firma de llamada (20.8.1), permitiendo que las funciones sean objetos de primera clase.

Como John Calsbeekadded: No hay nada en particular, en la norma relativa a las convenciones de llamada, pero los compiladores están haciendo su trabajo y los punteros de función contiene la información sobre la convención.

Con punteros a funciones que se necesitan para especificar la convención de llamada inusual:

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

No estoy seguro de que esto sea técnicamente una respuesta, ya que el estándar de C++ apenas menciona la convención de llamadas, y ciertamente no aparece aquí. La respuesta es que 'std :: function'" recuerda "el tipo de función que utiliza la magia del borrado de tipo, y los punteros de función en la mayoría de los compiladores razonables contienen información sobre la convención de llamada utilizada. –

+0

@JohnCalsbeek: Tiene razón, no hay nada más detallado en el estándar que mencionar la parte citada. Las convenciones de llamada son un territorio inexplorado, pero los compiladores se portan bien y hacen lo que se necesita. – Anonymous

+2

Lo más parecido es "vinculación C". Allí el compilador solo tiene que hacer que funcione, no hay nada en el estándar que haga responsable al programador. Por extensión, dado que el estándar no dice nada acerca de las convenciones de llamadas, ese silencio nuevamente lo convierte en una responsabilidad del compilador. – MSalters

Cuestiones relacionadas