Both MSVC and g++ accept the following code without warnings or errors and without giving any command line arguments except the filenames to compile.
I am certainly not recommending this way; Just showing that it is possible.
If not all compilers support it then I guess I was mistaken and I apologize.
template.h
Code:
template <int foo, int bar>
class X
{
public:
X();
~X();
int GetFoo(void) const;
int GetBar(void) const;
int GetSum(void) const;
private:
int _foo;
int _bar;
int _sum;
};
template.cpp
Code:
#include "template.h"
template <int foo, int bar>
X<foo,bar>::X() : _foo(foo), _bar(bar), _sum(foo+bar)
{
}
template <int foo, int bar>
X<foo,bar>::~X()
{
}
template <int foo, int bar>
int X<foo,bar>::GetFoo(void) const
{
return _foo;
}
template <int foo, int bar>
int X<foo,bar>::GetBar(void) const
{
return _bar;
}
template <int foo, int bar>
int X<foo,bar>::GetSum(void) const
{
return _sum;
}
struct instantiate_templates
{
// dummy member to instantiate X<1,2>'s constructor and destructor
X<1,2> x;
// call all of X<1,2>'s methods to instantiate them
instantiate_templates() { x.GetFoo(); x.GetBar(); x.GetSum(); }
} unused;
main.cpp
Code:
#include <iostream>
#include "template.h"
int main()
{
X<1,2> x; // works because X<1,2> is instantiated in template.cpp
/* X<1,3> y; // does not work because X<1,3> is not instantiated */
std::cout << x.GetFoo() << "+" << x.GetBar() << "=" << x.GetSum() << std::endl;
return 0;
}
The downside is that you need to know in advance which template arguments/typenames you are going to use and instantiate them explicitly. And all of X's methods gets called in unused's constructor which might be undesirable. Which is what I meant by using the header approach being less complicated.