views:

55

answers:

4

I can have a typedef function pointer in a class like this:

template<typename T>
class MyClass
{

public:

typedef T (*fptr)(T);

  void doSomething(fptr my_fptr) { /*...*/ }

};

and this works fine. but if I inherit from such a class, as below:

template<typename T>
class MyClass
{

public:

typedef T (*fptr)(T);

  virtual void doSomething(fptr my_fptr) = 0;

};

template<typename T>
class MyOtherClass: public MyClass<T>
{

public:

  void doSomething(fptr my_fptr) { /*...*/ }

};

the compiler complains that fptr is undefined. is there a way of inheriting function pointer typedefs like this? thanks, james

+1  A: 

You should be able to inherit public typedefs like that.

Did you try something like this to make sure the compiler know it's a parent type:

void doSomething(typename MyClass<T>::fptr my_fptr) { /*...*/ }
Mark B
this did it... I just missed the typename at the beginning.
james edge
A: 

I think the compiler needs more information due to the templating:

try typename MyClass<T>::fptr

messenger
+2  A: 

The problem is not with inheritance, but with the fact that a template is inheriting from the instantiation of another template passing it's own template argument as parameter. That is, it is inheriting from a dependent-type (MyClass<T> is dependent on the type T).

The language requires that the template is verified before performing the type substitution, and during that first pass, all non-dependent names are verified. When the compiler sees fptr it is not dependent on the type T, so it tries to locate it outside of your template as a namespace level symbol and fails. It is not allowed to instantiate MyBase with the type (there is no type for the substitution) and as such the whole MyBase is an unknown and no symbols can be looked up there (without substituting the type, the compiler cannot know whether there is an specific specialization of MyBase).

The simplest solution is adding a local typedef:

typedef MyBase<T> base_type;
typedef typename base_type::fptr fptr;

or fully qualify the call:

void doSomething( typename MyClass<T>::fptr ) ...
David Rodríguez - dribeas
A: 

The problem is that the definition is in a base class that depends on a template parameter (known as a dependent base class); it's not known until the template is instantiated what that base class actually is; different specialisations could have different members. So you have to explicitly state that it's a type, defined in the base class:

template<typename T>
class MyOtherClass: public MyClass<T>
{
    typedef typename MyClass<T>::fptr fptr;
    // now fptr is available in this class template
};

To access members of a dependent base class, you can refer to them as either MyClass<T>::member or this->member.

Mike Seymour