Зачем нам здесь имя типа?

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 ответа

Решение

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

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

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

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

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

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

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

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

Другие вопросы по тегам