Разница между добавлением и пропуском параметра шаблона для имени класса внутри конструктора
Я хочу знать, есть ли разница между:
template <typename T>
class foo{
foo<T>(){};
};
template<typename T>
class foo{
foo(){};
};
Кажется, что оба работают, но я не понимаю разницу между ними. Первый сбивает меня с толку, я не понимаю, какова роль
2 ответа
Согласно правилу имени введенного класса, это одно и то же.
$ 14.6.1 / 1 Локально объявленные имена [temp.local]:
Как и обычные (не шаблонные) классы, шаблоны классов имеют имя для введенного класса (раздел [класс]). Введенное имя класса может использоваться как имя шаблона или имя типа. Когда он используется со списком аргументов шаблона, в качестве аргумента шаблона для параметра шаблона или в качестве окончательного идентификатора в подробном спецификаторе типа объявления шаблона класса друга, он ссылается на сам шаблон класса., В противном случае оно эквивалентно имени шаблона, за которым следуют параметры шаблона шаблона класса, заключенного в <>.
Так foo
а также foo<T>
обратитесь к тому же самому здесь. Более конкретно,
Первый сбивает меня с толку, я не понимаю, какова роль
здесь.
Вы используете inject-class-name foo
с параметром шаблона T
(т.е. foo<T>
), который относится к самому классу шаблона.
Обратите внимание, что начиная с C++20 более длинная форма более недействительна, и вы должны использовать более короткую форму, основанную на вложенном имени класса .
См. [diff.cpp17]#class-2:
идентификатор простого шаблона больше не является допустимым в качестве идентификатора декларатора конструктора или деструктора.
Со следующим примером в спецификации:
template<class T>
struct A {
A<T>(); // error: simple-template-id not allowed for constructor
A(int); // OK, injected-class-name used
~A<T>(); // error: simple-template-id not allowed for destructor
};
И действительно, версия магистрали GCC отклоняет код, использующий более длинную форму (в то время как Clang 11 и GCC 10.2 все еще принимают его ).