views:

99

answers:

3

Hello

According to http://stackoverflow.com/questions/115703/storing-c-template-function-definitions-in-a-cpp-file

it is easy to seprate the interface and the implementation of a template class,

.h file

template<typename T> 
class foo 
{ 
   public: 
     foo();
     ~foo();
     void do(const T& t); 
}; 

.cpp file

template <typename T> 
void foo::foo() 
{ 
    // initiate 
} 

//destructor

template <typename T> 
void foo::do(const T& t) 
{ 
    // Do something with t 
} 

void foo<int> fi; 
void foo<std::string> fs; 

the trick being to specialise the template class by creating instances at the end of the .cpp file.

But what if this was a pure virtual template class

.h file

template<typename T> 
class foo 
{ 
   public:
     foo();
     ~foo(); 
     virtual void do(const T& t) = 0; 
}; 

and we derive a concrete class from this:

template<typename T> 
class foobar : public foo<T>
{ 
   public: 
     void do(const T& t); 
}; 

the source file for this class looks like

.cpp file

template <typename T> 
void foobar::do(const T& t) 
{ 
    // Do something with t 
} 

void foobar<int> fi; 
void foobar<std::string> fs;

and the source file for foo looks the same except the initiations are removed (since ofcourse now foo is an abstract class).

But there's a linker error now; foo<int>() is unresolved in the constructor of foobar<int>. This is fixed by moving the constructor and destructor of foo back to the header file from the source file.

So my question is how can we create abstract template base classes and keep the deifnition of the template class hidden in a source file??

+1  A: 

You need to instantiate the constructor in foo.cpp as well:

template void foo<int>::foo(const int&);

You will also have to do it for foobar for it to be usable.

Pavel Minaev
Thanks that works, so this means all members of the abstract class need to be initiated in the .cpp file for all the different specialisations. What a pain! Do you know of a more elegant way to seperate the interface and implementation of a template class?
aukm
@aukm : yes, see my answer.
Benoît
+2  A: 

I suggest you create an additional class for this :

#include <string>

template<typename T_Foo>
struct FooCompilation
{
  void operator()()
  {
    T_Foo foo;
    typedef typename T_Foo::T T;
    T t;
    foo.do(t);
  }
};

template FooCompilation<Foo<int> >;
template FooCompilation<Foo<std::string> >;

This should work because the compiler will try and instantiate all needed code for the code inside operator() to work.

Benoît
+1  A: 

You can explicitly instantiate a type without needing to instantiate a variable. Also, your existing code is hideously bugged and doesn't even come close to compiling.

template<typename T> 
class foo 
{ 
   public: 
     foo();
     ~foo();
     void something(const T& t); 
}; 

template <typename T> 
foo<T>::foo() 
{ 
    // initiate 
} 

//destructor

template <typename T> 
void foo<T>::something(const T& t) 
{ 
    // Do something with t 
} 
template<typename T>
foo<T>::~foo() {
}

template class foo<int>;

This will instantiate foo for int as a type but you don't need to mess around with variables.

DeadMG
Thanks, thats certainly a more manageable approach.
aukm