2014-01-20 5 views
1
template <typename dataType> 
**typename** List<dataType>::Node* List<dataType>::find(int index){ 
    Node *cur = head; 
    for(int i = 0; i < index; i++){ 
     cur = cur->next; 
    } 
    return cur; 
} 

Если я не использую, что я получаю следующее сообщение об ошибке:Зачем использовать ключевое слово "typename" для следующего определения?

need ‘typename’ before ‘List<dataType>::Node’ because ‘List<dataType>’ is a dependent scope 

Так что я прочитал wiki entry, но я не получаю причину этого конкретного примера.

+0

'Этот код выглядит так, как будто он должен компилироваться, но он неверен, потому что компилятор не знает, является ли T :: bar типом или значением.' – Gasim

+0

Правило большого пальца: возьмите самый правый '::'; если предмет справа от него - это тип, а вещь слева от него зависит от параметров шаблона каким-либо образом, используйте 'typename'. – Angew

ответ

7

Потому что, как и сообщение об ошибке, List<dataType>::Node является зависимым именем , то есть тем, что зависит от параметра шаблона. Представьте, что вы что-то вроде этого:

struct A { 
    typedef float t; 
}; 

struct B { 
    static int t; 
}; 

template <typename T> 
void func() 
{ 
    T::t * x; // pointer declaration, or multiplication? It depends... 
} 

Здесь A::t и B::t являются оба корректными выражениями C++, но означают совершенно разные вещи: первый тип, а второй имеет значение. Теперь, когда компилятор сначала анализирует функцию шаблона func() - чтобы проверить, является ли он синтаксически правильным, перед выполнением любой замены типа - он должен попытаться решить, что означает T::t * x. Ясно, что есть два возможных способа разобрать его, поэтому компилятор должен решить, что взять.

В некоторых случаях для компилятора достаточно «контекста», чтобы решить, ссылаетесь ли вы на тип или нет, но во многих случаях (например, этот пример) этого не происходит. Когда он не может решить, он предполагает, что вы говорите о значении - поэтому выше (надеюсь) даст вам ошибку об изменении переменной x. Если вы хотите, чтобы T::t рассматривался как тип, вам нужно указать его так явно, используя ключевое слово typename.

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