В случае, если неясно, что другие подразумевают под компилятором, не зная, что это тип: в тот момент, когда компилятор анализирует шаблон foo, он не знает, что вы не сделаете позже:
namespace std {
template<>
class vector<int> {
int iterator(void);
};
}
А затем создать экземпляр foo<int>
. Тогда vector<T>::iterator
будет функцией, а не типом, и соответствующая строка в foo не сможет проанализировать. Чтобы работать без посторонней помощи, компиляторам пришлось бы задерживать синтаксический анализ foo до его создания, и они нашли правильный класс, чтобы определить, является ли 'iterator' выражением типа или выражением значения. Я подозреваю, что это может привести к циклическим зависимостям, но, безусловно, будет особенно трудно реализовать. Таким образом, стандарт говорит, что выражение в шаблоне, которое зависит от параметра, считается не типом, если не указано иное. Есть два (я думаю) способа объявить его типом, который (1) использует его как базовый класс и (2) квалифицирует его как имя типа.
ОК, так что в этом примере вам фактически не разрешено специализировать std :: vector. И в действительности вектор имеет больше параметров шаблона, чем тот, который я использовал. Так что в вашем примере компилятор может теоретически предполагать больше, чем делает. Но в стандарте не предусмотрено, чтобы язык полагался на знание того, какие шаблоны находятся в пространстве имен std, поскольку (1) предполагается, что реализации могут реализовывать пространство имен std в обычных заголовках, которые компилятор обрабатывает так же, как и любые другие заголовки и (2) C ++ должен быть спроектирован как язык + библиотеки, а не как «язык со специальным синтаксисом для библиотек». Фактически, (1) и (2) являются одним и тем же требованием.