2009-07-14 2 views
13
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); 

} 

Почему typemame в remove() не требуется?Зачем нам здесь typename?

+0

Возможно, отредактируйте, чтобы уточнить, что строка, о которой вы говорите, является typename std :: list :: iterator it = std :: find (rep.begin(), rep.end(), itme); поскольку я думаю, что это ваше намерение. – aem

ответ

18

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

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

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

+1

Итератор потенциально может быть статической переменной-членом. И по умолчанию этот компилятор предполагает, что это так. Таким образом, ошибка компилятора. –

+0

Я считаю, что подтверждение того, называется ли этот язык «B ++», является серьезным нарушением коммерческой конфиденциальности? ;-) –

+0

Извините, что вернул это из мертвых, но через 8 лет мне любопытно, есть ли какая-либо дополнительная информация, которую вы можете раскрыть по поводу этого языка программирования. Хотя я не задерживаю дыхание. – Cebtenzzre

0

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

+0

Ах, этот ответ недействителен с этим разъяснением, извините! – DeusAduro

12

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

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

+0

+1 Удивительное объяснение! – AraK

1

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

В соответствии с this page «Используйте ключевое слово typename, если у вас есть квалифицированное имя, которое относится к типу и зависит от параметра шаблона».

Смежные вопросы