Зачем нам здесь имя типа?
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, если у вас есть полное имя, которое относится к типу и зависит от параметра шаблона".