Почему работает только адрес объявленной функции?

Я задал здесь вопрос о том, вызывает ли получение адреса функции компиляцию указанной функции конкретно в отношении замены -Отказ-это-не-ошибка. Самый прямой ответ на этот вопрос можно найти здесь:

Неформально объект используется odr, если его адрес взят или к нему привязана ссылка, а функция используется odr, если к ней сделан вызов функции или взят ее адрес. Если объект или функция используются odr, их определение должно существовать где-то в программе; нарушение этого является ошибкой времени компоновки.

Но все компиляторы, которые я тестировал, показывают, что это вполне выполнимо:

void foo(int);
auto bar = &foo;

Живой пример

Это не законно что ли? А если нет, то зачем он строится?


person Jonathan Mee    schedule 18.07.2016    source источник
comment
[basic.def.odr]/4 Каждая программа должна содержать ровно одно определение каждой не встроенной функции или переменной, которая используется в этой программе odr; диагностика не требуется. Подчеркнуто мной.   -  person Igor Tandetnik    schedule 18.07.2016
comment
Добавьте строку, печатающую содержимое bar, и вы должны получить сообщение об ошибке. Как правило, компиляторы не идут дальше, чем требует стандарт, и выдают ошибку только потому, что могут. Обычно они молча компилируют ваш код, а затем тонко взламывают его после того, как все тесты пройдены и пришло время выпуска.   -  person Revolver_Ocelot    schedule 18.07.2016


Ответы (2)


Из [basic.def.odr]:

Каждая программа должна содержать ровно одно определение каждой не встроенной функции или переменной, которая используется в этой программе odr; диагностика не требуется.

foo используется odr, но не имеет определения (предположительно - иначе вопрос спорный). Программа имеет неправильный формат, но поскольку диагностика не требуется, ее можно скомпилировать.

Как правило, именно компоновщик улавливает отсутствие определения, а не компилятор, поскольку определение может легко появиться в другой единице трансляции. Канонический пример — попытка передать static const int, которому не хватает определения, в вызов std::max() или std::min().

person Barry    schedule 18.07.2016

Ваш пример работает, потому что адрес никогда не используется, поэтому компоновщик никогда не ищет символ.

Если вы попытаетесь напечатать bar, связь не удастся.

void foo(int);
auto bar = &foo;
cout << (void*) bar;

http://ideone.com/97Eo6Z

person kubanrob    schedule 18.07.2016