Какая функция C позволяет классам шаблонов ссылаться на себя без аргументов шаблона?

#c #templates

#c #шаблоны

Вопрос:

Учитывая:

 template <typename T>
class C {
    C amp; operator    () { ... }
};
  

Почему / как C разрешено объявлять переменные и функции типа C вместо того, чтобы указывать имя C<T> ? Я действительно не думал об этом, прежде чем работать над шаблоном со многими параметрами, которые затрудняли бы написание «собственного типа».

Есть ли какие-либо особенности этого, о которых я должен знать?

Ответ №1:

[n3290: 14.6.1/1]: Как и обычные (не шаблонные) классы, шаблоны классов имеют введенное имя класса (пункт 9). Введенное имя класса может использоваться как имя шаблона или имя типа. Когда он используется со списком аргументов шаблона, в качестве аргумента шаблона для параметра шаблона или в качестве конечного идентификатора в детализированном спецификаторе типа объявления шаблона дружественного класса, он ссылается на сам шаблон класса. В противном случае, это эквивалентно имени шаблона, за которым следуют параметры шаблона класса, заключенного в <> .

Предположительно, это просто удобная функция.

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

1. Удивительно, что два человека поддержали это, в то время как я процитировал неправильный отрывок 😉 Нельзя отрицать силу цитирования стандарта — очевидно, любой части стандарта!

2. Ага, концепция, которой мне не хватало, была введена-class-name . Спасибо!

3. в c 11 имя класса не вводится, поэтому, я думаю, это вызовет ошибку

4. @Mr.Anubis: Приведенная выше цитата взята из C 11, и в ней говорится, что «шаблоны классов имеют injected-class-name «. Этот тестовый пример не является полным доказательством того, что я пока не доверяю реализациям, которые «полностью» следуют правилам языка C 11, но я думаю, что это, безусловно, достаточно хорошо.

5. пожалуйста, обратите внимание на это: ideone.com/wAcHv , вот почему я это сказал.

Ответ №2:

Это просто синтаксический сахар.

Удобно не менять подписи ваших методов, если вам нужно изменить параметры шаблона.

Ответ №3:

Почему / как C разрешено объявлять переменные и функции типа C, а не требуется указывать C?

Это просто указано следующим образом. Имя шаблона вводится в его тело и означает фактический тип (с аргументами).

Есть ли какие-либо особенности этого, о которых я должен знать?

Ничего серьезного. Вы просто должны помнить, что это не работает для базовых классов, поэтому для выполнения CRTP вам нужно сделать

 template <class T>
class A : public Base<A<T> > // not Base<A>
  

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

1. За исключением, если Base ожидается параметр шаблона шаблона. 😉

2. @Xeo: да, но в CRTP базовый класс ожидает производный тип.

3. Одно не исключает другое.