Рассмотрим следующий пример (в том же модуле перевода):
inline void f();
void f() {}
Что происходит при повторном объявлении f
? Является f
до сих пор считается inline
?
Я посмотрел в стандарте для этой ситуации, но я нашел обратное только в 10.1.6 / 6 [dcl.inline]:
[…] Если определение функции или переменной появляется в блоке перевода до его первого объявления как встроенного, программа является некорректной. […]
Я хотел бы некоторые ссылки в стандарте, которые определяют, что происходит в этой ситуации.
я видел это сообщение, но это не показывает явную ссылку в стандарте. Я склонен полагать, что нет такой ссылки.
Что происходит при повторном объявлении
f
? Являетсяf
до сих пор считаетсяinline
?
Да, f
до сих пор считается inline
,
Соответствующие разделы стандарта, относящиеся к семантике inline
Спецификатор функции можно найти в [Dcl.fct.spec]:
Объявление функции … с
inline
спецификатор объявляет встроенную функцию.inline
спецификатор указывает реализации, что внутреннее замещение тела функции в точке вызова должно быть предпочтительнее обычного механизма вызова функции.Встроенная функция должна быть определена в каждой единице перевода, в которой она используется odr, и должна иметь абсолютно одинаковое определение в каждом случае ([basic.def.odr]). [ Заметка: Вызов встроенной функции может встретиться до того, как ее определение появится в блоке перевода. — конечная нота ] Если определение функции появляется в модуле перевода до ее первого объявления как встроенного, программа является некорректной. Если функция с внешней связью объявлена встроенной в одной единице перевода, она должна быть объявлена встроенной во всех единицах перевода, в которых она появляется; Диагностика не требуется.
inline
Функция с внешней связью должна иметь одинаковый адрес во всех единицах перевода.
И в [Basic.def.odr]:
Каждая программа должна содержать ровно одно определение каждого не-рядный функция или переменная, которая используется в этой программе
Также см. Пример в [Dcl.stc] / 8:
void h(); inline void h(); // external linkage inline void l(); void l(); // external linkage
Интерпретация всего, что есть:
inline
в качестве спецификатора функции выступает в качестве флага, выражающего ваше желание сделать вызов данной функции встроенным. Как только он встречается в определенном объявлении функции, он остается «установленным» для этой конкретной перегрузки функции, и нет никакого способа «сбросить» его.
Неважно, если вы укажете inline
на декларация или определение функции, потому что определение это также декларация и потому, что несколько объявлений позволил.
Тем не менее inline
спецификатор должен встречаться до или же с определение функции и до используется одр (УСО использование означает, что компилятор должен фактически выдавать код, который вызывает функцию, или нужен ее адрес по любой причине).
inline
спецификатор имеет нет эффекта на связи функции, которая остается внешней для нестатических глобальных функций. Если адрес inline
Если используется функция (которая имеет внешнюю связь), компилятор выдаст для нее внешнее определение, убедившись, что компоновщик может сложить несколько определений, если это необходимо (например, используя слабый символ). Таким образом, адрес inline
Функция в разных TU будет одинаковой.
Как только функция объявлена inline
и имеет внешнюю связь, она должна быть объявлена inline
во всех других единицах перевода, которые используют odr.
Вы должны предоставить определение inline
функция в каждой единице перевода, которая использует odr, и она должна быть точно такой же.
Эффект переопределения указан в [Basic.def] / 1
Декларация может вводить одно или несколько имен в единицу перевода или переобъявить имена, введенные предыдущими объявлениями. Если это так, декларация определяет толкование и атрибуты этих имен.[…]
Таким образом, путем повторного выделения можно добавлять спецификации к имени, но не удалять их.