Разве компилятор Visual Studio 2008 не выполняет автоматическую трансляцию с использованием sqrt в C ++? - PullRequest
4 голосов
/ 16 марта 2010

Разве компилятор не должен автоматически приводить к удвоению в следующем? По крайней мере, по словам Вальтера Савича.

#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

Ответы [ 6 ]

8 голосов
/ 16 марта 2010

Проблема в том, что есть три версии 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;
4 голосов
/ 16 марта 2010

Неоднозначная ошибка вызова заключается в том, что она не знает, какую функцию вызывать, не в том, что она неявно преобразуется.

посмотрите на следующее. Если я создаю свою собственную функцию, которая принимает удвоение и возвращает удвоение, не возникает проблем с явным преобразованием. Поскольку ваше целое число может быть преобразовано в любую из трех перегрузок, оно не знает, что вызвать.

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
2 голосов
/ 16 марта 2010

Поскольку существует несколько функций sqrt (перегрузки) и более 1 могут принимать значение int в качестве параметра без потери точности, вы сами можете указать, какой (и это хорошо, потому что вы не не хочу, чтобы компилятор принимал за вас решения, основываясь на «косвенных» доказательствах - передавая int в sqrt).

0 голосов
/ 16 марта 2010

Есть несколько перегрузок в std :: sqrt в cmath. Один берет поплавок, а другой - двойник. Компилятор не может знать, какой из них вы хотите вызвать, и целые могут быть преобразованы в любой из них.

При отсутствии дополнительных перегрузок он автоматически приведёт к удвоению [как в случае с C], как вы ожидаете.

0 голосов
/ 16 марта 2010

Да, он должен автоматически приводиться от int к двойному g ++ компилирует это нормально, так что я полагаю, что VS не прав

РЕДАКТИРОВАТЬ: не уверен, почему мой ответ отрицательно. Но я думаю, что во время перегрузки функций в c ++ автоматическое преобразование всегда должно происходить с самым высоким типом данных, поскольку автоматическое преобразование возможно. например: если есть возможность конвертировать из в в long, с плавающей точкой и в двойное число, оно всегда должно выполнять преобразование из 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.

0 голосов
/ 16 марта 2010

C всегда возвращает двойную версию, если не вызывается sqrtf.

Попробуйте сделать звонок с (двойной)

Из MSDN: [

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

] 1

...