Question

I have this code, which doesn't compile (EDIT: compiled in VC, but not in GCC):

template<int N>
struct List
{
   template <class C>
   void clear() { }
};

template <int L>
class Test
{
public:
    List<L> list; // <--This line
    void method()
    {
       list.clear<int>(); // <-- Compile error here:  error: expected primary-expression before ‘int’

    }
};

How can I make it work? It seems the compiler (gcc) doesn't understand the context, because if in the marked line I replace L with a number, like List<1> list; then it compiles fine.

Was it helpful?

Solution

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.

OTHER TIPS

You need to put template keyword before clear to help compiler:

list.template clear<int>();
     ~~~~~~~~
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top