//Q: Why do I need to add "template" and "typename" in the bodies of template
//definitions?
//A: The meaning of a name used in a template definition may depend upon the
//template parameters, in which case it cannot automatically be determined when
//the template is defined. Early implementations of templates postponed
//resolution of all names used in a template to the time of instantiation, but
//this was found to be error-prone. It made it impossible to parse template
//definitions completely because many C++ syntax rules depend on distinguishing
//between names that refer to objects or functions, names that refer to types,
//and names that refer to templates.
//Later implementations parse templates as soon as they are defined. They require
//the programmer to specify which dependent names refer to types or templates, so
//that they can parse the templates without ambiguity. Where a dependent name is
//intended to refer to a type, it must generally be prefixed by the keyword
//typename. (This is not necessary when it is used in the list of base classes of
//a class template, since only type names can be used there.) Where a dependent
//qualified name or a prefix of such a name is intended to refer to a template,
//the last component of it must be prefixed by the keyword template. Note that
//some implementations may consider names to be dependent where the standard says
//they are non-dependent, and may therefore require additional uses of typename
//and template.
// Example:
template<typename Alloc>
class container_helper
{
typedef Alloc::value_type value_type;
// ill-formed: Alloc::value_type is assumed to be an object or function
typedef typename Alloc::value_type value_type;
// OK: Alloc::pointer is properly disambiguated
typedef Alloc::typename value_type value_type;
// ill-formed: "typename" must precede the whole qualified name
typedef std::pair<value_type, value_type> element_type;
// OK: value_type is resolved in the immediate scope
typedef typename Alloc::rebind<element_type>::other element_allocator;
// ill-formed: Alloc::rebind is assumed to be an object or function
typedef typename template Alloc::rebind<element_type>::other element_allocator;
// ill-formed: "template" must precede the last component of the
// template name
typedef typename Alloc::template rebind<element_type>::other element_allocator;
// OK: rebind is properly disambiguated
};
template<typename T, typename Alloc = std::allocator<T> >
class my_container : private container_helper<Alloc>::element_allocator
// OK: container_helper<Alloc>::element_allocator cannot be resolved
// but base names are assumed to be type names
{
};