3

I'm trying to compile some Microsoft Visual C++ code using g++. Now I've come across a compiler error which I really can't understand. The (simplified) code looks like this:

template<int X> struct A {
    template<class Ret> static Ret call() {
        return 0;
    }
};

template<int X> struct B : A<X> {
    int f() {
        return A<X>::call<int>();
    }
};

When I try to compile this with g++ (version 4.4.5), I get the following error:

main.cpp: In member function int B<X>::f(): 
main.cpp:16: error: expected primary-expression before int 
main.cpp:16: error: expected ; before int
main.cpp:16: error: expected unqualified-id before > token

If I remove the template type (Ret) from method A::call, the code compiles just fine. Can anybody see whats wrong here?

Thanks!

  • possible duplicate of [Where and why do I have to put the "template" and "typename" keywords?](http://stackoverflow.com/questions/610245/where-and-why-do-i-have-to-put-the-template-and-typename-keywords) – Mike Seymour Jan 25 '12 at 14:06

3 Answers3

5

You need the template keyword:

return A<X>::template call<int>();

call is a dependent name, meaning that its signification depends on a template parameter, which is not known when the compiler process f(). You need to indicate that call is a function template by prefixing it with the template keyword.

The same thing happens when you try to access a nested type: you need to add the typename keyword to indicate that the name denotes a type:

template <typename T>
struct A { typedef int type; };

template <typename T>
void f()
{
    typename A<T>::type i = 0; // notice "typename" here
}

And sometimes you even need to mix both:

template <typename T>
struct A
{
    template <typename U>
    struct inner { };
};

template <typename T>
void f()
{
    typename A<T>::template inner<int> var;
}

The use of these two keywords is thoroughly explained in the answers to this question: Where and why do I have to put the “template” and “typename” keywords? (thanks to @Björn Pollex for finding the link).

Community
  • 1
  • 1
Luc Touraille
  • 79,925
  • 15
  • 92
  • 137
5

A is a template, and without knowing X the compiler can't determine the contents of A<X>. Especially it doesn't know that call will end up being a template.

To tell that to the compiler you have to use the template keyword:

template<int X> struct B : A<X> {
    int f() {
        return A<X>::template call<int>();
    }
};
sth
  • 222,467
  • 53
  • 283
  • 367
3

You have to specify that the function you're calling is a template, as it's part of a template class. The compiler is not aware that any given A<X> has a template function named call, and therefore you need to help it.

template<int X> struct B : A<X> {
    int f() {
        return A<X>::template call<int>();
    }
};
Dave S
  • 20,507
  • 3
  • 48
  • 68