Ошибка компиляции шаблона - стандартная или нет? - PullRequest
5 голосов
/ 22 ноября 2011

У меня есть следующий код:

template<int k>
void foo()
{
}
int main(int argc, char* argv[])
{
    int k = 1000;
    foo<k>();
    return 0;
}

, который не компилируется, но если я объявляю k как const, он делает:

template<int k>
void foo()
{
}
int main(int argc, char* argv[])
{
    const int k = 1000;
    foo<k>();
    return 0;
}

Теперь я вижу логику, почему в первом случае он не компилируется, а во втором - компилируется, но это определено стандартом?

Ошибка, которую я получаю:

Error   1   error C2971: 'foo' : template parameter 'k' : 'k' : a local variable cannot be used as a non-type argument

, что не совсем понятно, поскольку k является локальной переменной также в том случае, если const ... верно?

Ответы [ 3 ]

4 голосов
/ 22 ноября 2011

В соответствии со стандартом, 14.3.2, это должно быть константное выражение:

Аргумент шаблона для нетипичного, нешаблонного параметра шаблона должен быть одним из:
- целочисленная константа-выражение целого или перечислимого типа ;или
- имя нетипового шаблона-параметра;или
- адрес объекта или функции с внешней связью, включая шаблоны функций и идентификаторы шаблонов функций, но исключая нестатические члены класса, выраженный как & id-выражение, где & является необязательным, если имя относится к функцииили массив, или если соответствующий шаблон-параметр является ссылкой;или
- указатель на член, выраженный, как описано в 5.3.1.

GCC 4.6.2 дает чуть более понятную ошибку:

error: 'k'не может появляться в константном выражении

2 голосов
/ 22 ноября 2011

§14.3.2.1 говорит [сокращенно]:

Аргумент шаблона для нетипичного, не шаблонного параметра шаблона должен быть одним из:
- целое константа-выражение целочисленного или перечислительного типа;

И §5.19.1 говорит [сокращенно, выделено мое]:

целочисленное константное выражение может включать только литералы, перечислители, константные переменные или члены-статические данные целочисленных типов или типов перечисления, инициализированных константными выражениями ...

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

Ошибка немного вводит в заблуждение, так как «локальная переменная не может быть использована в качестве нетипичного аргумента» - это правда в общем , но с некоторыми ограничениями это прекрасно.

2 голосов
/ 22 ноября 2011

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

template<int& k>
void foo()
{
}
int main(int argc, char* argv[])
{
    int k = 1000;
    foo<k>();
    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...