2013-04-08 3 views
22

При ответе this SO question я нашел в стандарте (уже C++ 03, еще в C++ 11), что вы можете использовать только адреса в качестве аргументов шаблона, отличных от типа, если они есть форма & id-expression (плюс некоторые исключения).Указатель как аргумент шаблона непигового типа

Но я не мог ответить почему это случай.

аргументы

14.3.2 шаблона не-типа [temp.arg.nontype]

Шаблон-аргумент для не-типа, не-шаблон Шаблон-параметр должен быть одним из:

[...]

- константа, выражение (5,19), что обозначает адрес объекта со статическим хранением> продолжительностью и внешней или внутренней связью или функцией с внешней или внутренней связью, в том числе шаблонов функций и шаблон функции -иды, но luding non-static class members, выражает (игнорируя круглые скобки) как & id-выражение, за исключением того, что & может быть опущен, если имя относится к функции или массиву и должно быть опущено, если соответствующий шаблон-параметр является ссылкой; [...]

(n3485, курсив мой)

Пример:

using TFoobar = int (*)(); 
template < TFoobar tp > struct foo_struct{}; 

int foobar() { return 42; } 
constexpr TFoobar pFoobar = &foobar; 

foo_struct < &foobar > o0; // fine 
foo_struct <pFoobar> o1; // ill-formed 

Я предполагаю, что это что-то делать с фазами перевода, а именно компилятор ничего не знает о адресах. Но почему это не разрешено? Должна ли компилятор использовать что-то похожее на макроподстановку, чтобы заменить pFoobar на &foobar?

+1

Очень хороший вопрос. –

+1

Я бы предположил, что это вопрос внесения консервативных изменений.C++ 11 полон действительно строгие способы для языка делать вещи, чтобы облегчить работу компилятора. Возможно, возможно расширить C++ 11, чтобы разрешить вышеупомянутое, но это вопрос для C++ 14 или за его пределами! – Yakk

+0

[Есть предложение] (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4268.html), чтобы удалить эти ограничения. – dyp

ответ

1

Рассмотрите классы Foo<&X> и Foo<&Y>, как со статическим элементом int Bar. Линкер должен быть в состоянии определить, имеет ли ваша программа 1 или 2 Bar объектов. Теперь подумайте, что компоновщик также является стороной, наиболее вероятно ответственной за присвоение значений &X и &Y.

Посмотрите на стандарт снова. Как написано, компилятору не нужно связывать фактический адрес с компоновщиком. Вместо этого он передает id-expression. Линкеры уже вполне способны определить, совпадают ли два id-expression, даже до назначения им числового адреса.

+1

Я знаю, что вместо фактического адреса можно использовать замену. Но как это отвечает на мой вопрос, почему объект 'constexpr' не может использоваться как аргумент шаблона указателя? – dyp

+0

И, чтобы добавить к комментарию DyP, если указатель constexpr был создан, его значение может быть вычислено и передано компоновщику (либо '& id', либо' nullptr') (и больше: это не противоречит вашему ответу). – Synxis

+0

@Synxis: Нет, компилятор не может вычислить значение указателя a (constexpr) для функции, так как компоновщик будет предоставлять функции свой адрес. – MSalters

0
  1. Он не может быть переменной, поскольку переменные устанавливаются только во время выполнения.
  2. Это не может быть constexpr, так как значение адреса не может быть известно во время компиляции; в большинстве случаев он будет исправлен только после перемещения перед исполнением.
  3. Теоретически это может быть арифметическое выражение (даже если оно не разрешено в стандарте), но в общем случае адреса элемента массива вы можете просто использовать &arr[i] вместо arr + i.
+0

Что не может быть constexpr? Адрес функции известен во время компиляции (включая время ссылки). Кроме того, перемещение происходит главным образом для общих библиотек, в современных системах 'exe' часто не перемещаются. – Synxis

+0

Объявление 3: постоянное выражение _is_ разрешено в стандарте, если я его интерпретирую правильно; это просто запрещено для функций (функция ptrs). Хотя я вижу, почему арифметическое выражение не имеет особого смысла в функции ptr, выражение константы, оценивающее функцию ptr, имеет смысл для меня, см. Пример в моем OP (или исходном вопросе Synxis). – dyp

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