Я очень хорошо знаю, что передача непосредственно const char*
в качестве шаблона непигового параметра ошибочна, поскольку два идентичных строковых литерала, определенных в двух разных единицах перевода, могут иметь разные адреса (хотя большую часть времени компиляторы используют тот же адрес). Существует трюк, который можно использовать, см. Код ниже:
#include <iostream>
template<const char* msg>
void display()
{
std::cout << msg << std::endl;
}
// need to have external linkage
// so that there are no multiple definitions
extern const char str1[] = "Test 1"; // (1)
// Why constexpr is enough? Does it have external linkage?
constexpr char str2[] = "Test 2"; // (2)
// Why doesn't this work?
extern const char* str3 = "Test 3"; // (3) doesn't work
// using C_PTR_CHAR = const char* const; // (4) doesn't work either
extern constexpr C_PTR_CHAR str4 = "Test 4";
int main()
{
display<str1>(); // (1')
display<str2>(); // (2')
// display<str3>(); // (3') doesn't compile
//display<str4>(); // (4') doesn't compile
}
В основном в (1) мы объявляем и определяем массив с внешней связью, который затем может использоваться как параметр шаблона в (1 '). Я это очень хорошо понимаю. Однако я не понимаю:
-
Почему работает
constexpr
версия (2)? Уconstexpr
есть внешняя связь? Если нет, то определение одного и того же строкового литерала в другой единицы перевода может привести к дублированию экземпляра шаблона. -
Почему (3) и (4) не работают? Для меня это кажется вполне разумным, но компилятор не верит в это:
error: 'str3' не является допустимым аргументом шаблона, потому что 'str3' - это переменная, а не адрес переменной