Я пытаюсь внедрить встроенную функцию.
Нет причин использовать extern
с функцией. См. длительность хранения — привязка. Функции имеют внешнюю связь по умолчанию; чтобы не иметь внешней связи, необходимо сделать что-то особенное (например, поместить его в анонимное пространство имен или объявить его static
). Таким образом, обычное использование встроенной функции уже демонстрирует внешнюю связь без использования ключевого слова extern
.
Как я думал, это должно работать:
//a.cpp
inline void f(int) {}
//b.cpp
extern void f(int);
int main() { f(4); }
Затем, прочитав это ("1) Он должен быть объявлен inline
в каждую единицу перевода.").
Эта ссылка верна, но поищите еще немного, где говорится: "Определение встроенной функции [...] должно присутствовать в единице перевода, где к ней осуществляется доступ [...]." В вашем примере есть объявление f
в b.cpp
, но не определение. Если вы собираетесь вызывать f
из b.cpp
, вам нужно полное определение в этой единице перевода, например:
inline void f(int) {}
(Это тот же код, что и в a.cpp
.) Если вы опустите фигурные скобки, то у вас будет объявление, но не определение, что сделает незаконным вызов f
из этой единицы перевода.
По сути, очень сложно определить встроенную функцию вне файла заголовка, если вы не дадите ей внутреннюю связь. Это связано с тем, что для каждого исходного файла, использующего встроенную функцию, потребуется собственная копия тела функции, а это означает, что если вы измените функцию, вам нужно будет внести это изменение в несколько файлов. Уф. Не делай этого. Определите каждую из ваших inline
функций в заголовочном файле. Если вы думаете, что хотите определить его в исходном файле, вы, вероятно, неправильно понимаете, что означает «inline
».
Что означает "inline
"?
С точки зрения компилятора ключевое слово inline
(почти) ничего не значит. Это просто флаг в определении функции, который передается в объектный код, чтобы компоновщик его увидел. Компилятор обрабатывает функцию так же, как любую другую функцию. Функция может вызываться обычным образом, или ее вызовы могут быть встроенными, как и любая другая функция.
Единственный случай, когда компилятор может что-то сделать с флагом inline
, — это когда функция объявлена inline
, используется, но не имеет определения. Это ошибка, которая может быть обнаружена до того, как компоновщик вступит во владение. Это не должно быть перехвачено компилятором, но может быть. (Если он не будет обнаружен компилятором, он будет обнаружен компоновщиком.)
Переходим к этапу связывания. Когда компоновщик видит флаг inline
, он приостанавливает действие правила с одним определением для этой функции. Компоновщик ожидает увидеть определение функции в каждой единице трансляции, которая все еще использует функцию после оптимизаций компилятора. Он может выбрать любое из этих определений, которое будет служить окончательной реализацией. Отсюда и причина того, что все определения должны совпадать.
И это все. Ключевое слово inline
в основном означает, что определение функции находится в заголовочном файле. Это говорит компоновщику не жаловаться, когда это определение появляется в нескольких единицах перевода, потому что это ожидается.
Возвращаясь к вопросу, похоже, что целью было объявить функцию inline
, определение которой будет отображаться только в одной единице перевода. Другими словами, функция будет помечена как определенная в нескольких единицах перевода, но определение будет только в одной. Как-то нелогично, если не сказать откровенно противоречиво.
person
JaMiT
schedule
28.05.2019
extern inline void f(int) {}
выглядит немного странно. Вы дали определение функции, которая помечена как определенная в другом месте. - person alter igel   schedule 28.05.2019The definition of an inline function or variable (since C++17) must be present in the translation unit where it is accessed.
Функцияinline void f(int) {}
уже имеет внешнюю связь и должна быть определена вb.cpp
. Функция уже имеет внешнюю связь.static inline void f(int){}
имеет внутр. - person KamilCuk   schedule 28.05.2019extern inline void f(int);
позволит вам получить только адресf
, но не вызоветf()
напрямую. Для этого вам по-прежнему необходимо предоставить определение в каждой единице перевода. - person rustyx   schedule 28.05.2019inline
) и говорите ему пойти и поискать ее в другой единице перевода (extern
). - person Mirko   schedule 29.05.2019inline
может быть определена более чем в одной единице перевода (вот что это значит). Какой из нихextern
выберет? - person Mirko   schedule 29.05.2019extern
иinline
одновременно? - person Mirko   schedule 29.05.2019