Зачем нам здесь имя типа? - PullRequest
14 голосов
/ 14 июля 2009
template<class T>
class Set 
{
public:
   void insert(const T& item);
   void remove(const T& item);
private:
   std::list<T> rep;
}

template<typename T>
void Set<T>::remove(const T& item)
{
   typename std::list<T>::iterator it =  // question here
    std::find(rep.begin(),rep.end(),itme);
   if(it!=rep.end()) rep.erase(it);

}   

Зачем нужно имя типа в remove ()?

Ответы [ 4 ]

21 голосов
/ 14 июля 2009

В общем, C ++ нуждается в typename из-за неудачного синтаксиса [*], который он наследует от C, что делает невозможным без нелокальной информации сказать - например - в A * B;, есть ли A имена тип (в этом случае это объявление B в качестве указателя на него) или нет (в этом случае это выражение умножения - вполне возможно, начиная с A, для всего, что вы можете сказать без нелокальной информации , может быть экземпляром класса, который перегружает operator*, чтобы сделать что-то странное; -).

В большинстве случаев компилятор имеет нелокальную информацию, необходимую для устранения неоднозначности (хотя неудачный синтаксис по-прежнему означает, что низкоуровневому синтаксическому анализатору требуется обратная связь от высокоуровневого слоя, который хранит информацию таблицы символов) ... но с шаблонов это не делает (не в целом, хотя в этом конкретном случае это может быть технически незаконно специализировать std::list<T>, так что его ::iterator НЕ является именем типа; -).

[*] не только мое мнение, но и мнение Кена Томпсона и Роба Пайкса, в настоящее время моих коллег, которые заняты разработкой и реализацией нового языка программирования для внутреннего использования: этот новый язык программирования, в то время как его синтаксис в основном C-like, НЕ повторяет ошибки проектирования синтаксиса C - это новый язык (например, в старом добром Pascal), синтаксис достаточен для того, чтобы отличить идентификаторы, которые должны называть тип, от идентификаторов, которые не должны; -).

12 голосов
/ 14 июля 2009

Если вы говорите о typename, используемом с std::list<T>::iterator:

Типовое имя используется для пояснения того, что iterator - это тип, определенный в классе std::list<T>. Без typename std::list<T>::iterator будет считаться статическим членом. typename используется всякий раз, когда имя, которое зависит от параметра шаблона, является типом.

1 голос
/ 14 июля 2009

typename необходимо в вашем объявлении 'it', потому что в противном случае компилятор не будет знать, что это объявление типа, а не выражение.

Согласно этой странице , "используйте ключевое слово typename, если у вас есть полное имя, которое относится к типу и зависит от параметра шаблона."

1 голос
/ 14 июля 2009

Я думаю, что в общем случае вам нужно как typename / class T в объявлении класса, так и определения функций, потому что вы можете определить полные / частичные спецификации шаблона для определений функций. То есть. Вы могли бы специализировать свою функцию удаления для целых чисел, строк, кем бы это ни было. Так что в этом случае вы говорите компилятору «Это общий шаблон для любого типа», а затем вы можете определить ту же функцию, которая указана только для целых чисел.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...