Reputation: 149
I would like to define the explicit specialization of a template function in a cpp file. Is that possible? To be more concrete, I have the following code, which compiles without errors:
//class.h
class myclass
{
public:
/* Constructor */
myclass();
/* Trigger fcn */
template<typename T> T Trigger(T rn);
private:
/* Specializations of the templated Trigger(...) function */
template<> int Trigger<int>(int rn)
{
int_do(rn);
}
template<> double Trigger<double>(double rn)
{
double_do(rn);
}
}
However, I having the definitions in the header file looks weird for me, so I would like to separate the definitions from the declarations, something like this:
//class.h
class myclass
{
public:
/* Constructor */
myclass();
/* Trigger fcn */
template<typename T> T Trigger(T rn);
private:
/* Specializations of the templated Trigger(...) function */
template<> int Trigger<int>(int rn);
template<> double Trigger<double>(double rn);
}
and:
//class.cpp
/* Specializations of the templated Trigger(...) function */
template<> int myclass::Trigger<int>(int rn)
{
int_do(rn);
}
template<> double myclass::Trigger<double>(double rn)
{
double_do(rn);
}
Is there any way to to this?
Upvotes: 6
Views: 2744
Reputation: 81
In addition to earlier answer regarding the positioning of the specialization:
You can define template functions in a .cpp file. This also means that they can only be instantiated within this translation object/file. In your case, the partial specialization is declared in the .h, and other compilation units will expect their existence.
For example in file tmp.h:
#include <iostream>
class T {
public:
template <typename T> void foo(const T& t)
{
std::cout << "generic foo" << std::endl;
}
};
// forward declaration of specialization
template<> void T::foo(const double& t);
file tmp.cpp:
#include "tmp.h"
template <> void T::foo(const double& t)
{
std::cout << "double foo" << std::endl;
}
file main.cpp:
#include "tmp.h"
int main(int argc, const char** argv)
{
T t;
t.foo(1.0);
t.foo(1);
return 0;
}
Now compiling both .cpp files will work fine:
g++ main.cpp tmp.cpp -o tmp
./tmp
double foo
generic foo
without the definition of the specialization:
g++ main.cpp -o tmp
/tmp/ccpCJr3B.o: In function `main':
main.cpp:(.text+0x1f): undefined reference to `void T::foo<double>(double const&)'
collect2: error: ld returned 1 exit status
Upvotes: 1
Reputation: 254431
Your only error is declaring the specialisations inside the class. Declare them in the header, but outside the class:
class myclass
{
public:
myclass();
template<typename T> T Trigger(T rn);
};
/* Specializations of the templated Trigger(...) function */
template<> int myclass::Trigger<int>(int rn);
template<> double myclass::Trigger<double>(double rn);
and then you can define them in a source file, exactly as you have done.
Note that your first snippet doesn't compile (unless your compiler has a non-standard extension), since the specialisations can't be declared inside the class.
Upvotes: 10