Templates overloades and specializations

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



Answer this question

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

    I didn't modify anything! I actually copied your solution as is to an empty project. I'm using VC6 with service pack 6.
  • 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

    Oh I seeeee! Well thanks for all your help, at least now I know where the problem lies, I was going nuts over this!
  • th3Nu11

    -*-*- wrote:
    I didn't modify anything! I actually copied your solution as is to an empty project. I'm using VC6 with service pack 6.

    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.


  • Templates overloades and specializations