2

Have this basic hierarchy:

// header

class Base
{
    virtual void method() { }
    virtual ~method() { }
};

class Subclass : Base
{
    virtual void method() { }
    virtual ~method() { }
};

I wish to subclass Base with two explicit variations (without having to provide two implementations of Subclass if possible), so it has been suggested to use explicit template instantiation:

// header

class Base
{
    virtual void method() { }
    virtual ~method() { }
};

class Base1 : public Base { };
class Base2 : public Base { };

template <typename T>    
class Subclass : public T
{
    virtual void method();
    virtual ~method() { }
};

// cpp

template <typename T>
void Subclass<T>::method()
{
}

template class Subclass<Base1>;
template class Subclass<Base2>;

I'm getting this error:

there are no arguments to 'method' that depend on a template parameter, so a declaration of 'method' must be available

Is this the correct approach? I would clearly have to template Base in order to get this to compile, but with what?

Dan
  • 33,953
  • 24
  • 61
  • 87
  • Don't forget the virtual destructor. Like money and unlike sex, you need to ask for it or else you don't get it. – wilhelmtell Nov 17 '10 at 16:22

2 Answers2

2

You should to put the definition of your template class and functions in the header file (it must be visible to who uses them).

Only complete specializations can be declared only (and defined where your code has no visibility).

Besides, if you want to define a function of a class template out of the class (as you did) you must declare it as a template:

template< typename T > 
void Class<T>::method( )
{
}

Anyway, if I recall correctly, the error you quoted is given when you use the function method which is provided by the typename you're inheriting from (I think you haven't posted the piece of code that generates the error...): it can only be found when the template is actually instantiated, thus you need to explicitly say it depends on the template parameter.

Call method in this way:

T::method();
peoro
  • 25,562
  • 20
  • 98
  • 150
  • I'd ideally not like to put the definitions into the header file as there's a lot of computation and it makes the compile times go way up if I can avoid it? – Dan Nov 17 '10 at 16:56
  • So there's no way of using polymorphism to call method() without having to know what the base class is? – Dan Nov 17 '10 at 17:00
  • 2
    You're shit out of luck on wishing to have templates outside headers at this point. Try to talk your compiler vendor into implementing 'export' for templates...good luck. There's no way to call method() in the base without knowing what the base is within a derived that defines one. If you remove method() from Subclass it'll work. Otherwise you have to use the syntax mentioned in the answer. – Edward Strange Nov 17 '10 at 17:38
  • 2
    @Dan there is nothing wrong with keeping your templates in the .cpp file. Fix the two errors (the "template" one and the "T::method() "one) and you are fine. For the T::method bug, you may also [want to look here](http://stackoverflow.com/questions/4210108/cannot-access-data-member-in-a-class-template). I wish some people would stop preaching the "templates can only work inside headers" fallacy. – Johannes Schaub - litb Nov 23 '10 at 21:18
0

Brief summary of the problem and solution:

To use a method from a templated base class requires either using the template parameter:

T::method();

or simply using "this" to allow it to be found without explicitly knowing the template parameter:

this->method();

Thanks to those that pointed me towards finding this solution, I wasn't aware of this. Also wish to point out there isn't a problem with putting the templates in the cpp file.

Dan
  • 33,953
  • 24
  • 61
  • 87