O Autocast do compilador do Visual Studio 2008 não é dobrado com o SQRT no C ++?

StackOverflow https://stackoverflow.com/questions/2452510

  •  20-09-2019
  •  | 
  •  

Pergunta

O compilador não deve ser lançado automaticamente para um dobro a seguir? Pelo menos de acordo com 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
Foi útil?

Solução

O problema é que existem três versões de sqrt escolher a partir de:

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

Desde que você está passando em um int, o compilador promoverá seu argumento, mas é igualmente válido promover seu número inteiro a qualquer um dos tipos acima, por isso é ambíguo.

Você pode consertar isso simplesmente lançando explicitamente para um dos tipos acima, como em:

cout << "The square root of k is: " << sqrt((double)k) << endl;

Outras dicas

O erro ambíguo de chamada é que ele não sabe qual função chamar não é que não seja implicitamente convertendo.

Veja o seguinte. Se eu criar minha própria função que pega um dobro e retorna um dobro, não tem problema em conversão implicitamente. Como seu número inteiro pode ser convertido para qualquer uma das três sobrecargas, ele não sabe como ligar.

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

No entanto, se eu adicionar outra versão do MySQRT que leva um flutuador, crio um erro ambíguo de chamada.

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

Já que existem múltiplos Funções SQRT (sobrecarga) e mais de 1 pode aceitar um int como um parâmetro sem perder a precisão, cabe a você especificar qual (e isso é uma coisa boa, porque você não deseja que o compilador toma decisões para você com base em evidências 'circunstanciais' - passando um int para sqrt).

C sempre retorna a versão dupla, a menos que o SQRTF seja chamado.

Tente lançar sua ligação com (duplo)

Do msdn: [

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

]1

Existem várias sobrecargas no std :: sqrt no cmath. Um leva um flutuador e outro leva um dobro. O compilador não pode saber qual você deseja ser chamado e o INTS pode ser lançado em qualquer um deles.

Na ausência de sobrecargas adicionais, ele foi lançado automaticamente para dobrar [este é o caso em C] como você espera.

Sim, ele deve ser lançado automaticamente de int para o dobro. G ++ compila essa multa, então eu acho que vs está errado

EDIT: Não sei por que a resposta do MO é votada. Mas acho que durante a sobrecarga de função no C ++, a conversão automática deve sempre acontecer com um tipo de dados mais alto na conversão automática. Para Ex: Se houver uma opção para converter para Long, Float e Double, ele sempre deve fazer uma conversão INT para dobrar.

Eu tentei isso no G ++ e está chamando a função SQRT (dupla).

#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;
}

Portanto, a saída do typeId () é "D", o que significa que fez uma conversão automática de int para o dobro.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top