аргументы не типа шаблона

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

...постоянное выражение (5.19), которое обозначает адрес объекта со статической длительностью хранения и внешний или внутренний рычаг или функция с внешним или внутренним рычагом..."

в коде, показанном ниже, я не понимаю, почему "name2" и "name3" не допускаются как не тип аргумент шаблона. Я использую gcc 4.7.2 в Windows.

оба "name2" и "name3" являются именами массива и, следовательно, являются постоянными выражениями. Далее "name2" имеет внутреннюю связь, а "name3" имеет как статическую, так и внутреннюю связь.

template<char const *p> void f()
{

}

char name1[] = "Hi";
static char name2[]= "Hi";
const static char name3[]= "Hi";
char *name4 = "Hi";

int main()
{
    f<name1>();
    f<name2>();
    f<name3>();
    f<name4>();
}

2 ответов


Как правильно догадался @Nawaz, это ошибка реализации, а не эзотерический угол стандарта.

в частности, у gcc, похоже, есть проблемы с этим. За исключением последнего name4 что против Стандарта, остальная часть его компилируется отлично с лязгом


Я думаю, что проблема в том, что выражение, которое вы используете, на самом деле не указатели, а массивы, и распад указателя работает только для name1. Скорее всего, это ошибка компилятора, как любезно указал @KonradRudolph в комментарии, раздел 14.3.2 стандарта C++11 позволяет это, и между name1, name2 и name3.

в качестве обходного пути следующее будет компилироваться с GCC 4.7.2 с помощью -std=c++11:

template<char const *p> void f()
{
}

char name1[] = "Hi";
static char name2[]= "Hi";
const static char name3[]= "Hi";

int main()
{
    f<(char const*)&name1>();
    f<(char const*)&name2>();
    f<(char const*)&name3>();
}

В C++98 mode он не компилируется, потому что результат приведения никогда не является постоянным выражением, в то время как в C++11 это может быть.