tags:

views:

331

answers:

6

Shouldn't the compiler automatically cast to a double in the following? At least according to Walter Savitch.

#include <iostream>
#include <cmath>
using namespace std;

int main(){
    int k;
    for(k = 1; k <= 10; k++)
        cout << "The square root of k is: " << sqrt(k) << endl;
    return 0;
}//error C2668: 'sqrt' : ambiguous call to overloaded function
//Visual Studio 2008 on Win Vista
A: 

C always returns the double version unless sqrtf is called.

Try casting your call with (double)

From the MSDN: [

double sqrt(
   double x 
);
float sqrt(
   float x 
);  // C++ only
long double sqrt(
   long double x
);  // C++ only
float sqrtf(
   float x 
);

]1

+3  A: 

Ambiguous call error is that it doesn't know which function to call not that its not implicitly converting.

look at the following. If I create my own function that takes a double and returns a double it has no issue implicitly converting. Since your integer can be converted to any of three overloads it doesn't know what to call.

double mysqrt(double d)
{
   return d;
}
using namespace std;
int main(int argc, char ** argv)
{

    int k;
    for(k = 1; k <= 10; k++)
        cout << "The square root of k is: " << mysqrt(k) << endl;
    return 0;
}//Works Fine

However if I add another version of mysqrt that takes a float I create an ambiguous call error.

double mysqrt(float f)
{
    return f;
}
double mysqrt(double d)
{
    return d;
}
using namespace std;
int main(int argc, char ** argv)
{

    int k;
    for(k = 1; k <= 10; k++)
        cout << "The square root of k is: " << mysqrt(k) << endl;
    return 0;
}//error C2668: 'mysqrt' : ambiguous call to overloaded function
rerun
+6  A: 

The problem is that there are three versions of sqrt to choose from:

     double sqrt (      double x );
      float sqrt (       float x );
long double sqrt ( long double x );

Since you're passing in an int, the compiler is going to promote your argument but it's equally valid to promote your integer to any of the above types, so it's ambiguous.

You can fix this by simply explicitly casting to one of the above types, as in:

cout << "The square root of k is: " << sqrt((double)k) << endl;
Scott Smith
credit source: cplusplus.com ...
@Mac - I'll all for attributing sources, but ...seriously? For three lines that are prototypes out of the standard?
Scott Smith
Or since this is C++ static_cast so you can search it later.
Mark B
A: 

Yes, It should automatically cast from int to double. g++ compiles this fine so I guess VS is wrong

EDIT: not sure why mo answer is down-voted. But I think during function overloading in c++, automatic conversion should always happen to a highest data type in auto conversion is possible. for ex: if there is an option to convert from into to long,float and double, it should always does an int to double conversion.

I tried this in g++ and it is calling sqrt(double) function.

#include <iostream>
#include <cmath>
#include <typeinfo>
using namespace std;

int main(){
    int k;
    for(k = 1; k <= 10; k++)
        cout << "The square root of k is: " << sqrt(k) <<' '<<  typeid(sqrt(k)).name()<< endl;
    return 0;
}

So output of typeid() is "d" which means it has done an auto conversion from int to double.

kumar
Most likely reason for downvote: VS is not "wrong" (very unlikely for something like type conversion). The issue at hand is one of overload resolution, as explained by others. VS offers more than overloaded function in C++, and overload resolution cannot determine which one is the right one based on implicit type conversion. See here for an explanation: http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=/com.ibm.xlcpp8a.doc/language/ref/cplr315.htm. Hope this helps.
stephan
Try to define `double mysqrt(double v)` and `long double mysqrt(long double v)` and you will see that if fails.
Artyom
A: 

There are several overloads to std::sqrt in cmath. One takes a float and another takes a double. The compiler can't know which you want to be called, and ints can be cast into any of them.

In the absence of the additional overloads, it would automatically cast to double [this is the case in C] as you expect.

Dennis Zickefoose
+2  A: 

Since there are multiple sqrt functions (overloads) and more than 1 can accept an int as a parameter without loosing precision it is up to you to specify which (and this is a good thing because you don't want the compiler taking decisions for you based on 'circumstantial' evidence - passing an int to sqrt).

Eugen Constantin Dinca