Предположим, что мы имеем функцию шаблона с параметром не-типа const char *
следующим образом:
template <const char * MESSAGE> void print() {
std::cout << MESSAGE << '\n';
}
Использование этого шаблона не будет проблемой, поскольку журнал, как MESSAGE
, может быть выведен во время компиляции, поэтому следующие действия являются законными:
namespace {
char namespace_message[] = "Anonymous Namespace Message";
constexpr char namespace_constexpr_message[] = "Anonymous Namespace Constexpr Message";
}
char message[] = "Message";
constexpr char constexpr_message[] = "Constexpr Message";
int main()
{
print<namespace_message>();
print<namespace_constexpr_message>();
print<message>();
print<constexpr_message>();
return 0;
}
Но ниже ниже (см. здесь):
namespace {
const char namespace_const_message[] = "Anonymous Namespace Const Message";
}
const char const_message[] = "Const Message";
int main()
{
print<namespace_const_message>();
print<const_message>();
print<"Literal">();
return 0;
}
Ошибки, генерируемые вышеуказанным кодом, следующие:
значение '{anonymous}:: namespace_const_message' не используется в постоянном выражении
Я не понимаю, почему namespace_const_message
не используется в постоянном выражении, а namespace_message
-; если я должен сделать ставку на то, что один из них не может быть использован в постоянном выражении, я буду держать пари за константу, но это тот, который уже работает как постоянное выражение!
note: '{anonymous}:: namespace_const_message' не был объявлен 'constexpr'
namespace_message
не был объявлен как constexpr
и используется в константном выражении, и его значение выводится во время компиляции. Почему constexpr
требуется, если выражение const
и не требуется, если no-const?
То же самое относится к значениям вне анонимного пространства имен, я пытался заставить compile-time-constness помещать значения во внутреннее пространство связей, но очевидно, что я потерпел неудачу.
Наконец, последняя ошибка:
' "Literal" ' не является допустимым аргументом шаблона для типа 'const char *', потому что строковые литералы никогда не могут использоваться в этом контексте
Итак, неожиданно (по крайней мере, это было для меня неожиданностью) строковый литерал не может использоваться в качестве аргумента шаблона, но до тех пор, пока строка (ну, указатель на массив символов с нулевым символом) является компилятором, значение времени можно использовать в качестве параметров непигового шаблона так: они доступны во время компиляции, пока "они являются lvalue" (но они уже lvalues !).
Я пытаюсь угадать, почему строковый литерал никогда не может использоваться в этом контексте, и я полагаю, что два строковых литерала с одним и тем же содержимым не являются одинаковыми буквами (поскольку указатель, указывающий на содержимое, может быть разными), тогда как два интегральных литерала одинаковы (они являются значением, а не указателем на значение).
Итак, какой вопрос здесь?
- Почему
namespace_const_message
иconst_message
недоступны во время компиляции и поэтому запрещены в функции шаблонаprint
? - Мое предположение о правильности строковых литералов?
Спасибо.