¿Por qué necesitamos typename aquí?

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

¿Por qué se necesita el nombre de tipo en remove ()?

En general, C ++ necesita typename debido a la desafortunada syntax [*] que hereda de C, que hace que sea imposible sin información no local decir, por ejemplo, en A * B; si A nombra un tipo (en cuyo caso se trata de una statement de B como un puntero) o no (en cuyo caso se trata de una expresión de multiplicación, muy posible desde A , para todo lo que puede decir sin información no local, podría ser una instancia de una clase que sobrecarga al operator* para hacer algo extraño ;-).

En la mayoría de los casos, el comstackdor tiene la información no local necesaria para desambiguar (aunque la desafortunada syntax todavía significa que el analizador de bajo nivel necesita comentarios de la capa de nivel superior que conserva la información de la tabla de símbolos) … pero con plantillas no lo hace ‘t (no en general, aunque en este caso específico podría ser técnicamente ilegal especializar una std::list para que its ::iterator NO sea un nombre de tipo ;-).

[*] no solo mi opinión, sino también la opinión de Ken Thompson y Rob Pikes, actualmente mis colegas, que están ocupados diseñando e implementando un nuevo lenguaje de progtwigción para uso interno: ese nuevo lenguaje de progtwigción, mientras que su syntax es mayormente C-like , NO repite los errores de diseño de syntax de C – es el nuevo lenguaje (como por ejemplo, en el viejo Pascal), la syntax es suficiente para distinguir los identificadores que deben nombrar un tipo de los que no ;-).

Si está hablando de typename utilizado con std::list::iterator :

El nombre de tipo se utiliza para aclarar que el iterator es un tipo definido dentro de la clase std::list . Sin typename, std::list::iterator se considerará un miembro estático. typename se usa cuando un nombre que depende de un parámetro de plantilla es un tipo.

typename es necesario en su statement de ‘it’ porque de lo contrario el comstackdor no sabe que es una statement de tipo en lugar de una expresión.

Según esta página , “use la palabra clave typename si tiene un nombre calificado que se refiera a un tipo y dependa de un parámetro de plantilla”.

Creo que, en general, necesita tanto el nombre de tipo / clase T en la statement de clase como las definiciones de función porque puede definir especificaciones de plantilla completas / parciales para definiciones de funciones. Es decir. puedes especializar tu función de eliminación para enteros, cadenas, lo que sea que sea. Entonces, en este caso, le está diciendo al comstackdor “Esta es la plantilla general, para cualquier tipo”, luego podrá definir la misma función especificada solo para los enteros.