Страницы

Поиск по вопросам

вторник, 10 декабря 2019 г.

Почему нельзя использовать в аргументах шаблонов сущности с внутренней компоновкой?

#cpp


Почему нельзя использовать в аргументах шаблонов сущности с внутренней компоновкой?

template
class Template { ... };
Template<"literal"> T;            // Ошибка! 


Нельзя использовать и глобальный указатель:

template
class Template { ... };
char const *s = "Literal";
Template T;                    // Ошибка!


Интересуют физические причины этих ограничений, а не правила, как можно а как нельзя.
    


Ответы

Ответ 1



В первом случае использование невозможно, так как даже одинаковые строковые литералы не обязаны иметь одинаковые адреса в программе. Т.е. Template<"literal"> мог бы получать разный аргумент шаблона в зависимости от контекста (если бы это было разрешено). Более того, в черновике стандарта N4687 использование строковых литералов явно запрещено в шаблонах 17.3.2/2: For a non-type template-parameter of reference or pointer type, the value of the constant expression shall not refer to (or for a pointer type, shall not be the address of): a subobject (4.5), a temporary object (15.2), a string literal (5.13.5), Это касается как непосредственного указания литерала, так и переменной типа char const * (см. далее). Во втором случае ошибка из-за использования переменной, а не адреса, фиксированного на момент компиляции. Например, gcc даёт следующую ошибку: error: 's' is not a valid template argument because 's' is a variable, not the address of a variable Чтобы всё же использовать шаблон, можно заменить указатель массивом: const char s[] = "literal"; Template T; Внутренняя или внешняя компоновка (linkage) будет - не важно по современным меркам, главное, чтобы она была, т.е. нельзя, например, использовать локальные объекты: template class Template { }; const char i[] = "literal"; // internal linkage char e[] = "literal"; // external linkage int main() { char n1[] = "literal"; // no linkage const char n2[] = "literal"; // no linkage constexpr char n3[] = "literal"; // no linkage Template Ti; // ok Template Te; // ok Template Tn1; // error Template Tn2; // error Template Tn3; // error }

Комментариев нет:

Отправить комментарий