Ответ 1
При использовании параметров шаблона непигового типа вам необходимо указать константу. Если параметр шаблона непигового типа является указателем или ссылкой, достаточно указать константу, которая может быть определена во время привязки. В любом случае компилятор не примет ничего, что может быть мутировано после ссылки. Даже переменная, инициализированная во время ссылки, инициализируется слишком поздно:
print<char *, tag::array>(); // OK: the address of the array won't change
print<const char *, tag::carray>(); // OK: the address of the array won't change
print<char *, tag::ptr>(); // not OK: tag::ptr can change
print<const char *, tag::cptr>(); // not OK: tag::ptr can change
print<const char *const, tag::cptrc>(); // not OK: a [run-time initialized] variable
print<string, tag::str>(); // not OK: few types are supported (*)
print<const string*, tag::cstr>(); // not OK: tag::cstr has a different type
print<const string*, &tag::cstr>(); // (added) OK: address won't change
print<char *, ntag::array>(); // OK: address of array won't change
print<const char *, ntag::carray>(); // OK: address of array won't change (**)
print<char *, ntag::ptr>(); // not OK: ntag::ptr can change
print<const char *, ntag::cptr>(); // not OK: ntag::cptr can change
print<const char *const, ntag::cptrc>(); // not OK: a [run-time initialized] variable
print<string, ntag::str>(); // not OK: few types are supported (*)
print<const string*, ntag::cstr>(); // not OK: ntag::cstr has a different type
print<const string*, &ntag::cstr>(); // (added) OK: address won't change
Примечания:
- (*) Только целые типы, указатели и ссылки могут использоваться нестандартные параметры шаблона. Нет понятия констант определения пользователя, которые могут использоваться в качестве параметров шаблона.
-
(**) gcc не нравится это использование, пока clang нравится. gcc не принимает этот код, кажется, ошибка! Я не вижу никаких ограничений, которые запретили бы использование
const char[]
в качестве аргумента шаблона. Вместо этого в примере 14.3.2 [temp.arg.nontype] есть пример, который в точности эквивалентен:template<class T, const char* p> class X { / ... / }; X<int, "Studebaker"> x1; // error: string literal as template-argument const char p[] = "Vivisectionist"; X<int,p> x2; // OK
- Листинг строковых литералов с указателем не
const
наchar
в порядке, однако попытка изменить одно из этих значений - это поведение undefined. Я настоятельно рекомендую не использовать этот актерский состав! - Не злоупотребляйте
std::endl
: в вашем коде нет использовать дляstd::endl
вообще.