C ++ встроенная переопределение

Рассмотрим следующий пример (в том же модуле перевода):

inline void f();
void f() {}

Что происходит при повторном объявлении f? Является f до сих пор считается inline?

Я посмотрел в стандарте для этой ситуации, но я нашел обратное только в 10.1.6 / 6 [dcl.inline]:

[…] Если определение функции или переменной появляется в блоке перевода до его первого объявления как встроенного, программа является некорректной. […]

Я хотел бы некоторые ссылки в стандарте, которые определяют, что происходит в этой ситуации.

я видел это сообщение, но это не показывает явную ссылку в стандарте. Я склонен полагать, что нет такой ссылки.

3

Решение

Что происходит при повторном объявлении 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, и она должна быть точно такой же.

1

Другие решения

Эффект переопределения указан в [Basic.def] / 1

Декларация может вводить одно или несколько имен в единицу перевода или переобъявить имена, введенные предыдущими объявлениями. Если это так, декларация определяет толкование и атрибуты этих имен.[…]

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

0

По вопросам рекламы [email protected]