Разве компилятор Visual Studio 2008 не выполняет автоматическую настройку double с помощью sqrt в C ++?
Вопрос
Разве компилятор не должен автоматически приводить к двойному в следующем?По крайней мере, по словам Уолтера Сэвича.
#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
Решение
Проблема в том, что существует три версии sqrt
на выбор:
double sqrt ( double x );
float sqrt ( float x );
long double sqrt ( long double x );
Поскольку вы проходите в int
, компилятор будет продвигать ваш аргумент, но в равной степени допустимо продвигать ваше целое число к любому из вышеперечисленных типов, так что это неоднозначно.
Вы можете исправить это, просто явно приведя к одному из вышеуказанных типов, как в:
cout << "The square root of k is: " << sqrt((double)k) << endl;
Другие советы
Ошибка неоднозначного вызова заключается в том, что он не знает, какую функцию вызывать, а не в том, что она не преобразуется неявно.
посмотрите на следующее.Если я создам свою собственную функцию, которая принимает double и возвращает double, у нее не возникнет проблем с неявным преобразованием.Поскольку ваше целое число может быть преобразовано в любую из трех перегрузок, оно не знает, что вызывать.
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
Однако, если я добавлю другую версию mysqrt, которая принимает значение с плавающей точкой, я создам неоднозначную ошибку вызова.
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
Поскольку существует множество функции sqrt (перегружает) и более 1 могут принимать int в качестве параметра без потери точности, вам решать, какой именно (и это хорошо, потому что вы не хотите, чтобы компилятор принимал решения за вас на основе "косвенных" доказательств - передавая int в sqrt).
C всегда возвращает двойную версию, если только не вызывается sqrtf.
Попробуйте выполнить свой вызов с помощью (double)
Из MSDN:[
double sqrt(
double x
);
float sqrt(
float x
); // C++ only
long double sqrt(
long double x
); // C++ only
float sqrtf(
float x
);
]1
Существует несколько перегрузок для std::sqrt в cmath.Один берет float, а другой - double.Компилятор не может знать, какой из них вы хотите вызвать, и целые числа могут быть преобразованы в любой из них.
При отсутствии дополнительных перегрузок он автоматически преобразуется в double [это имеет место в C], как вы и ожидали.
Да, он должен автоматически преобразовываться из int в double.g ++ компилирует это нормально, так что я думаю, VS ошибается
Редактировать:не уверен, почему мой ответ отклонен.Но я думаю, что во время перегрузки функций в c ++ автоматическое преобразование всегда должно происходить с максимально возможным типом данных при автоматическом преобразовании.для бывших:если есть возможность преобразовать из into в long, float и double, она всегда должна выполнять преобразование int в double .
Я попробовал это в g ++, и это вызывает функцию sqrt (double).
#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;
}
Таким образом, вывод typeid() равен "d", что означает, что он выполнил автоматическое преобразование из int в double.