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

Хотя стандарты C ++ не позволяют использовать строковые литералы в качестве шаблонов-аргументов, допускаются такие вещи:

ISO/IEC 14882: 2011

14.3.2 Template non-type arguments [temp.arg.nontype]

2 [ Note: A string literal (2.14.5) does not satisfy the requirements of any of these categories and thus is not an acceptable template-argument. [ Example:

template class X {/.../};

X x1;//error: string literal as template-argument

const char p[] = "Vivisectionist";
X x2;//OK

—end example ] —end note ]

Итак, почему следующий код дает мне ошибку во всех компиляторах (gcc 4.7.2, MSVC-11.0, Comeau)?

template 
void foo() {}

int main()
{
   const char str[] = "str";
   foo();
}
4
nl ja de
+1 он работал с чем-то вроде MSCV 6 или 7. Но в прошлый раз я попробовал его больше не компилировать :-( Рад, что вы задали вопрос.
добавлено автор Stephane Rolland, источник

2 ответы

Перемотайте несколько строк.

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

5
добавлено

Обратите внимание, что работает следующая модификация:

template 
void foo() {}

char str[] = "str";

int main() {
    foo();
}

См. http://www.comeaucomputing.com/techtalk/templates/#stringliteral для короткое объяснение.

4
добавлено
Вы можете сохранить константу, но тогда вы должны убедиться, что она имеет внешнюю связь. (Константные переменные в области пространства имен имеют внутренние по умолчанию.) Таким образом, будет работать extern char const str [] = "str"; . Как будет static char const str []; , если он является членом класса. (Интересный момент: использование static в области пространства имен гарантирует, что он не будет работать, const или нет. Но вы должны сделать его static if это член класса.)
добавлено автор James Kanze, источник
@Cornstalks Произошло изменение между C ++ 03 и C ++ 11. C ++ 03 необходимы аргументы шаблона для внешней привязки; C ++ 11 (я думаю) допускает внутреннюю связь. Поскольку, вообще говоря, пока нельзя рассчитывать на наличие C ++ 11, лучше использовать только внешнюю связь.
добавлено автор James Kanze, источник
@Cornstalks C ++ 03 требует внешней связи, а константа в пространстве имен имеет внутреннюю привязку. Это не ошибка компилятора (но можно утверждать, что это ошибка в стандарте).
добавлено автор James Kanze, источник
Итак, это ошибка компилятора?
добавлено автор FrozenHeart, источник
@jpalecek: Вы имели в виду http://ideone.com/t4jgHb и http://ideone.com/0VBoi3 ? Кроме того, да, я удалил свой комментарий.
добавлено автор Cornstalks, источник
@mkluwe: Согласно цитате nm, он должен быть объектом со статической продолжительностью хранения и внешней или внутренней связью (так что, если const не имеет нестатического времени хранения, он должен теоретически работать , независимо от того, является ли это внешней или внутренней связью). Я слишком ленив, чтобы понять, как const влияет на все это. Но я бы сказал, что это ошибка компилятора, потому что код примера стандартного отказа: http://ideone.com/YQNCfB
@JamesKanze: А что из 14.3.2/1: "постоянное выражение (5.19), которое обозначает адрес объекта со статическим временем хранения и внешним или внутренней связью "?
добавлено автор Cornstalks, источник
@mkluwe: Приятно знать, но все еще не удается выполнить код примера, заданный стандартом C ++? Если стандарт говорит, что const должен работать, а это не так, я бы сказал, что это ошибка компилятора.
добавлено автор Cornstalks, источник
Вы правы, удаляя const . Однако я думаю, что он просто демонстрирует ошибку компилятора в константах обработки кода, потому что const char p [] = "" по-прежнему определяет внешний объект.
добавлено автор jpalecek, источник
@Cornstalks: О да, const важен здесь: сравните ideone.com/rY7ZWI и ideone.com/u4LbEC (хотя вы правы, не используя локальную переменную, важно, я просто пытался изменить варианты его и наткнулся на const вещь ...)
добавлено автор jpalecek, источник
Хм, я думаю, что термин в стандарте - это «внешняя связь» (а не «внешний объект»). Объекты, имеющие область пространства имен, объявленную const , имеют внутреннюю связь. Я не хороший адвокат языка, но я не думаю, что это ошибка компилятора.
добавлено автор mkluwe, источник
Цитата @Cornstalks n.m. может быть из стандарта C ++ 11. Код компилируется с помощью gcc 4.72 с помощью -std = c ++ 11 при изменении const на constexpr .
добавлено автор mkluwe, источник
Я не могу ответить на это. Я использовал constexpr из-за формулировки константного выражения . В приведенном выше примере используется const , но IIRC в стандартах ISO, примеры являются ненормативными.
добавлено автор mkluwe, источник
pro.cxx
pro.cxx
3 049 участник(ов)

C/C++ chat 0. Простые вопросы, лабы и о IDE — в чат новичков @supapro 1. Не хамим, не переходим на личности, не вбрасываем утверждения без доказательств 2. No Ads, offtop, flood Объявления о вакансиях и евенты - в лс @AlexFails https://t.me/ProCxx/259155

supapro.cxx
supapro.cxx
1 925 участник(ов)

Чат для тех, кто немного знает C++, простые вопросы по реализации, синтаксису и ide – сюда, а для другого есть: /Главный чат по серьезным вопросам — @ProCxx /Чат по обсуждению всего — @fludpac

C++ Russia
C++ Russia
384 участник(ов)

Сообщество разработчиков C++ в Telegram.

cxx.Дискуссионная
cxx.Дискуссионная
298 участник(ов)

это не двач, общайтесь вежливо; разговор на почти любые темы; Не согласны с баном? В лс @AlexFails, @ivario

C++ для маленьких и тупых
C++ для маленьких и тупых
105 участник(ов)

Лоу левел (по среднему IQ участников) чатик ExtremeCode @extremecode Флудилка @extremecode_rest