std :: function如何知道调用约定?

Ben*_*min 9 c++ calling-convention c++11

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;
}
Run Code Online (Sandbox Code Playgroud)

我担心我怎么分配__stdcall functionstd::function对象.但是没有任何指定调用约定,它看起来好像工作.怎么std::function知道调用约定是什么?

Ano*_*ous 6

std::function 能够存储使用任何调用约定的函数指针.

§20.8.11.2:

函数类模板提供了多态包装器,它概括了函数指针的概念.在给定调用签名(20.8.1)的情况下,包装器可以存储,复制和调用任意可调用对象(20.8.1),从而允许函数成为第一类对象.

正如John Calsbeek所 补充的那样:关于调用约定的标准中没有特别的内容,但是编译器正在完成它们的工作,函数指针包含有关约定的信息.

使用函数指针,您需要指定不寻常的调用约定:

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;
Run Code Online (Sandbox Code Playgroud)

  • 我不确定这在技术上是一个答案,因为C++标准几乎没有提到调用约定,它肯定不在这里.答案是`std :: function`"记住"使用类型擦除的魔力的函数类型,并且大多数合理编译器中的函数指针包含有关所使用的调用约定的信息. (5认同)
  • 最接近的是"C连接".在那里,编译器必须使其工作 - 标准中没有任何东西使程序员负责.通过扩展,由于标准对调用约定没有任何说明,因此沉默再次使其成为编译器的责任. (2认同)