Search code examples
c++templatesambiguoussqrt

Removing ambiguity when using sqrt() function in a template class


I have a complex number class where I am trying to implement a function to work out the modulus (which requires the used of a sqrt).

My header file is as follows:

#ifndef MY_CLASS_H
#define MY_CLASS_H

template <class T> class complex
{
    // function to overload operator<< a friend
    template <class T>
    friend std::ostream& operator<< (std::ostream &os, const complex<T> &z);
private:
    T re,im;
public:

    // Constructors & destructor
    complex(){re=im=0;}
    complex( const T& r, const T& i ) : re(r), im(i) {}
    ~complex(){}

    // Return real component
    T realcomp() const {return re;}
    // Return imaginary component
    T imagcomp() const {return im;}
    // Return modulus
    double modulus() {return sqrt(im*im + re*re);}

etc....

The compiler outputs the error:

error C2668: 'sqrt' : ambiguous call to overloaded function
 could be 'long double sqrt(long double)'
 or       'float sqrt(float)'
 or       'double sqrt(double)'

which I know is telling me that the sqrt needs to know what type of data it is passing through it.

For my program, im and re will take either double or int values.

Am I right in saying sqrt will only take floating values? If so how do I force im and re to floating points without a 'loss of data' warning. Can I do this without converting them?


Solution

  • No, sqrt generally does not take floats. What it takes depends a on your libraries. In your case, you have several overloaded sqrt functions, one takes float, one takes double, and one takes long double.

    The problem you have, is none of them take int, and there are multiple conversions from int to a type that you could be used, so the compiler makes you choose (by casting). If you are only using double or int, then cast to double -- there will be no loss of presision. If you want to use long double at some point, cast to that.

    double modulus() {return sqrt((double)im*im + re*re);}