I want to create a function that returns the absolute value of a number. This number could be real (int, double, etc) or complex (of real, double, etc). I currently have the following:
//---------------------------------------------------------------------
template<class data_t>
data_t myAbs(data_t x)
{
return ((x > 0) (x):(-x));
}
//---------------------------------------------------------------------
template<class data_t>
data_t myAbs<complex<data_t> >(complex<data_t> x)
{
return (sqrt(x.real() * x.real() + x.imag() * x.imag()));
}
//---------------------------------------------------------------------
This compiles. However, when I call the function with a complex argument, the first function is called. I've tried several possibilities for the second function:
//template specialization, won't compile because data_t is unknown
template<>
data_t myAbs<complex<data_t> >(complex<data_t> x)
//pure overload
//If I declare it in the header I get a "fatal error C1001: INTERNAL COMPILER ERROR" (even though I used the option "No precompiled headers" in my VC6 settings.
//If I don't declare it in the header it compiles but still doesn't get called
template<class data_t>
data_t myAbs(complex<data_t> x)
Can anyone tell me the correct way to do this Also header vs cpp seems to make a big difference. Any ideas

Templates overloades and specializations
Mortsdeh
The following works as I would expect it to. In your first post, the complex<> specialization of myAbs<>() wasn't declared properly. You're creating a full and explicit specialization of myAbs<>(), so the template keyword goes away on behalf of myAbs<>(). But because the argument for the myAbs template function is itself a templated type, you then need to parameterize that argument with its corresponding template keyword.
I didn't analyze your second post.
#include <complex>
using namespace std;
template<class data_t>
data_t myAbs(data_t x)
{
return ((x > 0) (x):(-x));
}
template<class T>
T myAbs(complex<T> x)
{
return (sqrt(x.real() * x.real() + x.imag() * x.imag()));
}
int main()
{
complex<double> a(1.0,4.0);
double r = myAbs( a );
double s = myAbs( -1.2 );
printf("r=%g, s=%g\n",r,s);
return 0;
}
TerryYoung
adorer
Thanks for replying.
Your solution works for real numbers but gives me the following errors for complex arguments:
error C2667: 'myAbs' : none of 2 overload have a best conversion
error C2668: 'myAbs' : ambiguous call to overloaded function
Any idea why
JuniorBR
th3Nu11
And that explains it. VC6 has poor template support, to say the least. To add to your woes; it's no longer supported.
You should consider upgrading to the far superior VC8
KitWest
Just wanted to add two more solutions I've tried:
//---------------------------------------------------------------------
1) Creating an overloaded template helper class:
//template class for real numbers
template<class data_t>
struct absclass
{
static data_t myAbsClass(data_t x)
{
return ((x > 0) (x):(-x));
}
};
//template class for complex numbers
template<class data_t>
struct absclass<complex<data_t> >
{
static data_t myAbsClass(complex<data_t> x)
{
return (sqrt(x.real() * x.real() + x.imag() * x.imag()));
}
};
//template function for both real and complex numbers
template<class data_t>
data_t myAbs(data_t x)
{
return(absclass<data_t>::myAbsClass(x));
}
I get the following compile errors:
error C2989: 'absclass<class complex<data_t> >' : template class has already been defined as a non-template class
error C2988: unrecognizable template declaration/definition
If, instead of declaring the second class (complex) as
template<class data_t>
struct absclass<complex<data_t> >
I declare it without the specialization
template<class data_t>
struct absclass
then I get a slightly different error:
error C2953: 'absclass' : template class has already been defined
//---------------------------------------------------------------------
2) Creating a template helper class with an overloaded function
//template class for both real and complex numbers
template<class data_t>
struct absclass
{
static data_t myAbsClass(data_t x)
{
return ((x > 0) (x):(-x));
}
static data_t myAbsClass(complex<data_t> x)
{
return (sqrt(x.real() * x.real() + x.imag() * x.imag()));
}
};
//template function for both real and complex numbers
template<class data_t>
data_t myAbs(data_t x)
{
return(absclass<data_t>::myAbsClass(x));
}
This compiles but doesn't solve anything: Still, the first function is called for complex numbers.
//---------------------------------------------------------------------
Would be truly grateful for any help, am slowly getting desperate :-(
Roof Top Pew Wee
I don't understand. My code is using complex arguments. Can you elaborate by pasting your modification to my code
Thanks.
PS I edited my previous post, adding the words and explicit since specializations are also implicitly done by the compiler, which is the wrong choice in your case.