When you instantiate List
with a template argument of Test
, it becomes a dependent template. The compiler can't instantiate it when parsing Test
, because it does not know value of L
yet and for all it knows List
might be specialized differently for different values of L
. So the compiler can't be sure clear
is a template and gets confused. You have to add the template
keyword to disambiguate it like:
list.template clear<int>();
// ^^^^^^^^ here just before the dependent template
When you replace L
with 1
, the template no longer depends on parameters of the enclosing template, so the compiler instantiates and sees clear
is a template and does not need the disambiguation.
All members of dependent templates need to be disambiguated. The compiler always assumes they are values (function or data), so types have to be disambiguated with typename
and templates with template
.
This use of template
keyword is part of the specification. MSVC can parse many cases, including this one, without it, but it is a MSVC extension. Gcc is correct in requiring the template
keyword here.
See this answer for exhaustive discussion.