In case it isn't clear what the others mean by the compiler not knowing that it's a type: at the point where the compiler parses template foo, it doesn't know that you won't later do:
namespace std {
template<>
class vector<int> {
int iterator(void);
};
}
And then instantiate foo<int>
. Then vector<T>::iterator
would be a function, not a type, and the relevant line in foo should fail to parse. To work without help, compilers would have to hold off parsing foo until it's instantiated, and they've found the right class to determine whether 'iterator' is a type expression or a value expression. I suspect this could lead to circular dependencies, but would certainly be especially painful to implement. So the standard says that an expression in a template which is dependent on a parameter is assumed not to be a type unless stated to be. There are two (I think) ways to state it to be a type, which are (1) use it as a base class, and (2) qualify it with typename.
OK, so in this example you're actually not allowed to specialize std::vector. And vector actually has more template parameters than just the one I've used. So in your example, the compiler could in theory assume more than it does. But the standard doesn't make special provision for the language to rely on knowledge of what templates are in namespace std, because (1) the intention is that implementations can implement namespace std in normal headers treated the same as any other headers by the compiler, and (2) C++ is supposed to be designed as language+libraries, not as "language with special-case syntax for libraries". In fact, (1) and (2) are sort of the same requirement.