Ответ 1
Я не знаю каких-либо платформ, где ABI отличается, но даже если соглашения о вызовах на C и С++ одинаковы, стандарт С++ требует, чтобы компилятор выдавал диагностику для этой программы. Связывание с указателем на функцию-с-языком C - это другой тип привязки к указателю на функцию-с-С++, поэтому вы должны иметь возможность перегружать run()
следующим образом:
extern "C" int run(int (*f)(int), int x) { return f(x); }
extern "C++" int run(int (*f)(int), int x) { return f(x); }
Теперь, когда вы вызываете run(times)
, он должен вызывать второй, поэтому следует, что первый из них не является вызываемым (отсутствует преобразование из указателя-в-функцию-с-C-language-linkage в указатель- to-function-with-С++ - language-linkage), поэтому исходный код должен вызвать диагностику компилятора. Большинство компиляторов ошибаются, хотя, например, http://gcc.gnu.org/bugzilla/show_bug.cgi?id=2316
N.B. Компилятор Solaris диагностирует несовместимые языковые связи в качестве предупреждения:
"t.c", line 11: Warning (Anachronism): Formal argument f of type extern "C" int(*)(int) in call to run(extern "C" int(*)(int), int) is being passed int(*)(int).
Если вы перегрузите run
с помощью функции extern "C++"
, она правильно вызывает extern "C++"
one для run(times)
.