Являются ли внешние функции "С" отдельным типом?

Из проекта С++ 11, 7.5 (пункт 1):

Два типа функций с различным языком Связи - это разные типы, даже если они идентичны друг другу.

Таким образом, я могу сделать перегрузку на основе языковых связей:

extern "C" typedef void (*c_function)();
typedef void (*cpp_function)();

void call_fun(c_function f)
{
}
void call_fun(cpp_function f)
{
}

extern "C" void my_c()
{
}
void my_cpp()
{
}
int main()
{
    call_fun(my_c);
    call_fun(my_cpp);
}

Но с GCC 4.7.1 этот пример кода дает сообщения об ошибках:

test.cpp: In function 'void call_fun(cpp_function)':
test.cpp:7:6: error: redefinition of 'void call_fun(cpp_function)'
test.cpp:4:6: error: 'void call_fun(c_function)' previously defined here

И с CLang++:

test.cpp:7:6: error: redefinition of 'call_fun'
void call_fun(cpp_function f)
     ^
test.cpp:4:6: note: previous definition is here
void call_fun(c_function f)
     ^

Теперь вопросы:

  • Насколько я понимаю стандарт? Действительно ли этот код действителен?

  • Кто-нибудь знает, если это ошибки в компиляторах, или если они намеренно делают это таким образом для целей совместимости?

Ответы

Ответ 1

Это известная ошибка в gcc, и они записывают, что она не соответствует требованиям, поскольку эта ошибка блокирует ошибку uber-ошибки "С++ 98".

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=2316

Проверьте дату создания.

Там некоторое обсуждение к концу, о практических возможностях введения исправления. Таким образом, ответ на ваш последний вопрос - "оба": это ошибка, и ошибка была намеренно оставлена ​​для совместимости.

Другие компиляторы с одной и той же проблемой могли бы сделать ошибку самостоятельно, но я думаю, что они скорее знают, что это неправильно, но хотят быть совместимыми с gcc.

Ответ 2

Код явно важен. g++ (и ряд других компиляторов) являются bit lax (мягко говоря) об интеграции связи в тип.

Ответ 3

Для чего это стоит, этот код также не может скомпилироваться с настройками по умолчанию в VS2012:

(8) error C2084: function 'void call_fun(c_function)' already has a body
(4) see previous definition of 'call_fun'
(19) error C3861: 'call_fun': identifier not found
(20) error C3861: 'call_fun': identifier not found