2012-03-04 3 views
11

Есть ли способ использовать адреса функций в постоянных выражениях?Почему адреса функций не являются постоянными выражениями

void foo() 
{} 

int main() 
{ 
    static_assert(&foo, "test error"); 
} 

Это не скомпилирует.

ошибка C2057: ожидается постоянное выражение

Намерение за это, что я хочу, чтобы сравнить два адреса функций во время компиляции.

ответ

6

Это определенно ошибка компилятора.

Функции могут использоваться в качестве аргумента шаблона для шаблона, что означает, что они являются выражениями const. (См. ideone).

Кроме того, приведенный выше код компилируется с gcc 4.6.1, хотя идеон не компилирует его, но ideone использует gcc-4.5.1, у которого есть ошибка в отношении вашего кода.

+4

Я думаю, что это может быть немного сложнее. Одна из проблем с адресами функций заключается в том, что компилятор не обязательно * знает * его значение (он может быть определен в другой единицы перевода или вообще не определен. Каков ожидаемый результат (в момент компиляции *) '& foo 'для этих случаев? (Я не говорю, что это невозможно сделать, это выражение считается * odr-use *, поэтому компилятор может предположить, что он должен быть определен и позволить компоновщику разрешить адрес сбой, если он не определен, но Я бы подошел к стандарту для авторитетного ответа на вопрос. –

+2

Функции известны во время компиляции, но их адреса нет. Символьные имена используются во время компиляции компоновщика на карту памяти позже. Чтобы еще больше усложнить ситуацию, после шаблоны были введены в C++, линкеры почти повсеместно начали складывать функции, имеющие идентичный скомпилированный код. Таким образом, две разные функции могут иметь один и тот же адрес во время выполнения **. Компилятор не должен знать об этом. –

+0

S Ince функции могут быть перемещены во время загрузки (думаю, Windows DLL), то я не вижу, как «& foo» может быть известен, в общем, до тех пор, пока программа не будет запущена. –

3

Это мое понимание, FWIW:

Функция типа известно время компиляции, а функция адрес известен только во время связи. Таким образом, вы можете использовать типы функций в качестве параметров шаблона, но адреса во время компиляции не являются постоянными/известными.

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

+0

Адреса даже не известны во время соединения. Код часто переносится при загрузке. –

+1

Правда, но относительные адреса в одном загружаемом модуле * известны во время соединения, так что переходы функций могут быть «подключены». Моя точка зрения состоит в том, что адрес функции может быть логически взят во время выполнения (то есть: язык гарантирует, что это законно), но не время компиляции. – Nick

Смежные вопросы