Hello,
I have a question about templates. I would like to have a templated class that contains, say, an array of either float's or double's.
I can write a clone() function that duplicates it. No problem. However, I would like to have another function called cast() that does a translation back and forth between double and float. This has been somewhat discussed before but I don't think the problem is the same:
stackoverflow.com/questions/714213/c-template-casting
The problem I have is a compiler error, not a linker error. The error message is:
main.cpp: In function `void caster()':
main.cpp:63: error: expected primary-expression before "double"
main.cpp:63: error: expected `;' before "double"
main.cpp:64: error: expected primary-expression before "float"
main.cpp:64: error: expected `;' before "float"
main.cpp:65: error: expected primary-expression before '>' token
main.cpp:65: error: expected primary-expression before ')' token
I dumped the code below. The lines 63, 64, and 65 are where I commented with "Error here".
By the way, my compiler is "GNU C++ version 3.4.5 20051201 (Red Hat 3.4.5-2) (x86_64-redhat-linux) compiled by GNU C version 3.4.5 20051201 (Red Hat 3.4.5-2)".
After some Googling, it turns out that someone has already experienced this problem:
gcc.gnu.org/ml/gcc-help/2006-04/msg00022.html
There is a solution here:
gcc.gnu.org/ml/gcc-help/2006-04/msg00023.html
But when the original poster asks as to why it works, the answer is not very clear:
gcc.gnu.org/ml/gcc-help/2006-04/msg00025.html
Unfortunately, the link is dead, and I don't own the third edition of Stroustrup. Now, I have my fix, my code works. But, Stackoverflow, why does it work?
#include <stdio.h>
// =================== This would be the header ===================
template <class T>
class foo
{
public:
foo(const T val) {d_data = new double; *d_data = val;}
virtual ~foo() {delete d_data;};
foo* clone() const;
template<class U>
foo<U>* cast() const;
private:
double *d_data;
};
// =================== This would be the implementation of the class ===================
template<class T>
foo<T>* foo<T>::clone() const
{
return new foo<T>(*d_data);
}
template<class T>
template<class U>
foo<U>* foo<T>::cast() const
{
return new foo<U>(*d_data);
}
template class foo<float>;
template class foo<double>;
template foo<float>* foo<float>::cast() const;
template foo<float>* foo<double>::cast() const;
template foo<double>* foo<float>::cast() const;
template foo<double>* foo<double>::cast() const;
// =================== Using the class ===================
template <class T>
void caster()
{
foo<double> *f1 = NULL;
foo<float> *f2 = NULL;
foo<T> *f3 = NULL;
// I am looking at something that compiles
// I don't care about linking for now
// This will crash at runtime because of
// NULL, but that's just an example
f1->cast<double>(); // compiler OK
f1->cast<float>(); // compiler OK
f1->cast<T>(); // compiler OK
f2->cast<double>(); // compiler OK
f2->cast<float>(); // compiler OK
f2->cast<T>(); // compiler OK
f3->cast<double>(); // Error here
f3->cast<float>(); // Error here
f3->cast<T>(); // Error here
f3->foo<T>::template cast<double>(); // It works!
f3->foo<T>::template cast<float>(); // It works!
f3->foo<T>::template cast<T>(); // It works!
}
int main(int argc, char **argv)
{
return 0;
}