Почему ключевое слово «typename» необходимо использовать перед квалифицированными зависимыми именами, а не перед квалифицированными независимыми именами?
class A
{
static int iterator;
class iterator
{
[...]
};
[...]
};
Я (кажется, я) понимаю причину, почемуtypename
здесь необходимо:
template <class T>
void foo() {
typename T::iterator* iter;
[...]
}
но я не понимаю причину, почемуtypename
здесь не нужно:
void foo() {
A::iterator* iter;
[...]
}
Кто-нибудь может объяснить?
РЕДАКТИРОВАТЬ:Причину, по которой компилятор не имеет проблем с последним, я нашел, что на него хорошо ответили в комментарии:
на случай, еслиA::iterator
Я не понимаю, почему компилятор не спутал бы его сstatic int iterator
? - xcrypt
@xcrypt, потому что он знает, что обаA::iterator
S есть и могут выбрать, какой из них в зависимости от того, как он используется - Сет Карнеги
Причина, по которой нужен компиляторtypename
перед квалифицированными зависимыми именами, на мой взгляд, очень хорошо ответил в принятом ответе Керрек С.Б. Не забудьте также прочитать комментарии к этому ответу, особенно этот от iammilind:
"T :: A * x ;, это выражение может быть истинным для обоих случаев, когда T :: A является типом, а T :: A является значением. Если A является типом, то это приведет к объявлению указателя; если A является значением, то это приведет к умножению. Таким образом, один шаблон будет иметь разное значение для двух разных типов, что недопустимо ".