Почему взятие адреса функции, которая объявлена только работающей?
Я задал здесь вопрос о том, вызывает ли принятие адреса функции компиляцию указанной функции, особенно в отношении ошибки замещения-не-ошибки. Самый прямой ответ на это можно найти здесь:
Неформально, объект используется odr, если его адрес взят, или ссылка привязана к нему, и функция используется odr, если выполняется вызов функции или принят его адрес. Если объект или функция используются odr, их определение должно существовать где-то в программе; нарушение этого является ошибкой во время соединения.
Но все протестированные мной компиляторы показывают, что это вполне выполнимо:
void foo(int);
auto bar = &foo;
Это не законно, не так ли? Но если нет, то почему это здание?
2 ответа
Из [basic.def.odr]:
Каждая программа должна содержать ровно одно определение каждой не встроенной функции или переменной, которая используется в этой программе в виде odr; Диагностика не требуется.
foo
используется odr, но не имеет определения (предположительно - в противном случае вопрос является спорным). Программа плохо сформирована, но поскольку диагностика не требуется, ее можно скомпилировать.
Как правило, компоновщик обнаруживает отсутствие определения, а не компилятор, поскольку определение может легко появиться в другом модуле перевода. Канонический пример пытается передать static const int
который не имеет определения в призыв к std::max()
или же std::min()
,
Ваш пример работает, потому что адрес никогда не используется, поэтому компоновщик никогда не ищет символ.
Если вы попытаетесь напечатать bar
связывание не удается.
void foo(int);
auto bar = &foo;
cout << (void*) bar;