Зачем нам здесь typename?
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()?
Ответы
Ответ 1
В общем, С++ нуждается в typename
из-за неудачного синтаксиса [*], который он наследует от C, что делает невозможным без нелокальной информации говорить - например, - в A * B;
- имена A
тип (в этом случае это объявление B
в качестве указателя на него) или нет (в этом случае это выражение умножения - вполне возможно, так как A
, для всего, что вы можете сказать без нелокальной информации, может быть экземпляром класса, который перегружает operator*
, чтобы сделать что-то странное; -).
В большинстве случаев у компилятора есть нелокальная информация, необходимая для устранения неоднозначности (хотя неудачный синтаксис по-прежнему означает, что низкоуровневому парсеру нужна обратная связь с уровня более высокого уровня, который хранит информацию в таблице символов)... но с шаблонов это не так (не в общем, хотя в этом конкретном случае было бы технически незаконным специализировать std::list<T>
, чтобы его ::iterator
не являлся типом имени; -).
[*] не только мое мнение, но и мнение Кен Томпсона и Роба Пайкса, в настоящее время моих коллег, которые заняты разработкой и внедрением нового языка программирования для внутреннего использования: этот новый язык программирования, в то время как его синтаксис в основном C-like, НЕ повторяет ошибки дизайна синтаксиса C - это новый язык (например, в хорошем старом Pascal), синтаксиса достаточно, чтобы отличать идентификаторы, которые должны называть тип из тех, которые не должны; -).
Ответ 2
Если вы говорите typename
, который используется с std::list<T>::iterator
:
Имя_файла используется, чтобы уточнить, что iterator
- это тип, определенный в классе std::list<T>
.
Без typename std::list<T>::iterator
будет считаться статическим членом. typename
используется, когда имя, которое зависит от параметра шаблона, является типом.
Ответ 3
typename необходимо в вашем объявлении 'it', потому что иначе компилятор не знает, что это объявление типа, а не выражение.
В соответствии с эта страница, "Используйте ключевое слово typename, если у вас есть квалифицированное имя, которое ссылается на тип и зависит от параметра шаблона."
Ответ 4
Я думаю, в общем, вам нужно как typename/class T в объявлении класса, так и определения функций, потому что вы можете определить полные/неполные спецификации шаблона для определений функций. То есть. вы могли бы специализировать функцию удаления для ints, строк, независимо от того, что это произойдет. Поэтому в этом случае вы сообщаете компилятору "Это общий шаблон для любого типа", а затем вы можете определить ту же функцию, что и для целых чисел.