0

I have the following code:

template <typename T>
struct Data {
   struct Embed
   { 
      T t;
   };
};

struct Functor {
  template <typename T>
  void foo( typename Data<T>::Embed & e) {}
};
template <typename T, typename F>
struct Caller
{
  F f;
  template <typename T>
  void invoke() {
    typename Data<T>::Embed e;
    f.foo<T>(e); //compiler error pointed this line
   }
 };

Then I specialized the template as:

 Caller<int, Functor> c;
 c.invoke();

compiler error is : error: expected primary-expression before '>' in f.foo<T>(e); line. It seems compiler suddenly doesn't know what T is even it is specified in the template declaration on the function.

Take out the explicit specified T in foo.invoke(e) line will result could not deduce template parameter 'T'

How do I fix this? (I still want to keep the functionality that Caller can have generic functor and functor's function can be templated).

user2426361
  • 387
  • 1
  • 7
  • 13
  • It could be that you are reusing the same template name for `invoke()` as you have for `Caller`. I don't think that is allowed. – NathanOliver May 29 '15 at 17:41

2 Answers2

2

You are using:

template <typename T>
void invoke() {
   typename Data<T>::Embed e;
   f.foo<T>(e); //compiler error pointed this line
}

inside Caller even though T is one of the parameters of Caller. Remove the line

template <typename T>

and use just:

void invoke() {
   typename Data<T>::Embed e;
   // f.foo<T>(e);   //compiler error pointed this line
   f.template foo<T>(e); // Need the template keyword here.
}

However, as @Nawaz pointed out in a comment, that changes the semantics of invoke. If T in invoke was meant to be different than the T used to instantiate Caller, then it will be better to use a different name, say U.

R Sahu
  • 204,454
  • 14
  • 159
  • 270
2

The problem is that f is of type F which is template parameter, f.foo is a dependent name and which happens to be a function template. So you've to use template in a very weird way:

f.template foo<T>(e);

For further explantion, see these:

Also, I'd advise you to use U as template parameter for the function template invoke if at all it needs to be a template, else you can make it a normal function (i.e if the T of invoke is ought to be same as T of the enclosing class template).

Hope that helps.

Community
  • 1
  • 1
Nawaz
  • 353,942
  • 115
  • 666
  • 851