Как std::function знает о соглашении о вызовах?

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;
}

Я был обеспокоен тем, как назначить __stdcall function в std::function объект. Но без какого-либо указания соглашения о вызовах, похоже, работает нормально. Как может std::function знаете, что такое соглашение о вызовах?

1 ответ

Решение

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;
Другие вопросы по тегам