Подтвердить что ты не робот

Аргументы шаблона non type

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

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

В приведенном ниже коде я не понимаю, почему "name2" и "name3" не разрешены как аргументы шаблона non type. Я использую 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>();
}
4b9b3361

Ответ 1

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

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

Ответ 2

Я думаю, что проблема заключается в том, что используемое вами выражение не является на самом деле указателями, а массивами, а распад указателя работает только для name1. Скорее всего, это ошибка компилятора, как это было сказано в примечании @KonradRudolph, в разделе разрешен раздел 14.3.2 стандарта С++ 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>();
}

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