You need to use typename for the so-called "dependent types". These are types that depend on the template argument and are unknown until the template is created. This is probably best explained with an example:
struct some_foo { typedef int bar; }; template< typename Foo > struct baz { typedef Foo::bar barbar;
This typedef definition of barbar is one that requires typename so that the compiler can check the template for blatant syntax errors before it is created with a particular type. The reason is that when the compiler sees the template for the first time (when it has not yet been created with the specific parameters of the template), the compiler does not know if the type Foo::bar type. As far as I know, I could intend baz create instances with types like this
struct some_other_foo { static int bar; };
in this case, Foo::bar will refer to the object, not the type, and the definition of baz::bar will be syntactically meaningless. Without knowing whether Foo::bar type, the compiler cannot check anything in baz , directly or indirectly using barbar for even the barbar typos until baz is created. Using the correct typename , baz looks like this:
template< typename Foo > struct baz { typedef typename Foo::bar barbar; barbar f();
Now the compiler at least knows that Foo::bar must be a type name, which makes barbar a type name. So the declaration of f() also syntactic.
By the way, there is a similar problem with templates instead of types:
template< typename Foo > struct baz { Foo::bar<Foo> create_wrgl();
When the compiler "sees" Foo::bar , it does not know what it is, so bar<Foo may just be a comparison, leaving the compiler confused about the final > . Here you also need to give the compiler a hint that Foo::bar should be the name of the template:
template< typename Foo > struct baz { Foo::template bar<Foo> create_wrgl(); };
Beware: especially Visual C ++ still does not implement the correct two-phase search (essentially: it does not check patterns until they are created). Therefore, it often accepts erroneous code that skips typename or template .