To complete @Pieter answer, which is correct, some more info on how templates are processed.
First of all, templates are only compiled whenever they are instantiated, so that if you do not instantiate the template for a given type then the code will never be compiled.
Now, when you do instantiate a template, there is a two steps validation of the template code. First the template is verified for correctness regardless of what the instantiation type is. To check with a simpler to understand example:
#include "a.h"
template <typename T> void f( T const & )
{
T::type x; // is T::type a type?
};
int main()
{
A a;
f( a );
}
During the first phase, the template is checked for syntax correctness without considering what A really is. At this time the syntax A::type could be a type by the name of 'type' or it could be a static variable by the same name.
struct A { // version 1
typename int type;
};
struct A { // version 2
static std::string type;
};
std::string A::type = "A";
In the first case, type is indeed a type, in the second it is not. Now the standard states that if it is really a type then the programmer of the template must state so to inform the compiler with the syntax above:
template <typename T> void f( T const & a )
{
typename T::type x; // define a variable x of type T::type
}
Now, to complete the processing, the compiler must check that the template code is not only correct in itself, but that when it is instantiated with the particular type T it is also correct. This is what the compiler performs during the second stage of validation. It applies the type and rechecks for errors.
In your case, it is a little more controversial, as everyone (but the compiler) knows that std::list::const_iterator is a type for any given T. Well, it does not need to be. From a language standpoint, some code could provide a template specialization for a particular data type T that is different to the general list template. The compiler cannot know whether that could be so.
Note that it would be horribly wrong to specialize a template in the std namespace with something that changes behavior in as much as redefining the iterator types. But the compiler sees std namespace just as any other namespace, and list as any other templated class.