Стандарт ясно дает понять, что языковая связь действительно является свойством самой функции type:
Все типы функций, имена функций с внешней связью и имена переменных с внешней связью имеют языковую связь.
В случае, если это было недостаточно ясно, есть примечание (выделено мной), которое делает предполагаемое значение недвусмысленным:
[Примечание: Поскольку языковая связь является частью типа функции, при косвенном обращении через указатель на функцию C функция, на которую ссылается результирующее lvalue, считается функцией C . — конец примечания ]
Более того,
Два типа функций с разными языковыми связями являются разными типами, даже если в остальном они идентичны.
Итак, ответ на ваш первый вопрос:
- Да,
extern "C"
является частью типа функции.
Однако большинство компиляторов не различают типы функций с языковой компоновкой C и C++. Это, например, давняя ошибка в GCC (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=2316; см. список дубликатов). Я не читал внимательно всю ветку, но похоже, что большая часть существующего кода сломается, если GCC начнет применять правило, согласно которому они действительно являются разными типами. Возможно, именно поэтому другие компиляторы также не соответствуют стандарту.
Учитывая это, ответ на ваш второй вопрос будет выглядеть так:
- Вероятно, нет переносимого способа выполнить эту проверку во время компиляции. Конечно, после перевода вы всегда можете зайти и посмотреть объектный файл и посмотреть, искажено ли имя или нет.
Но теоретически ваше статическое утверждение должно работать так, как вы думаете. Вот только на практике это не так.
Дополнение:
Если мое понимание стандарта правильное, то, например, следующий шаблон функции
template <typename R, typename... A>
void f(R(*)(A...));
нельзя создать экземпляр для создания функции, которая принимала бы указатель на функцию с привязкой к языку C в качестве аргумента, поскольку тип R(*)(A...)
является "указателем на функцию с привязкой к языку C++, принимающую аргументы типов A...
и возвращающую R
".
Если бы компиляторы действительно работали так, легко понять, как можно было бы в общем определить, имеет ли функция связь с языком C или C++.
Но этот пример также должен прояснить, насколько сильно бы сломался существующий код, если бы компиляторы действительно работали таким образом.
person
Brian Bi
schedule
30.10.2014
extern "c"
, которые я нашел в Интернете, говорится об изменении имени, но не о соглашении о вызовах. - person Inbae Jeong   schedule 30.10.2014__attribute__
для компилятора). Оба типа, которые вы сравниваете, являютсяint (*)(int)
. - person keltar   schedule 30.10.2014