¿Por qué es complejo < double > * int no definido en C ++?
-
10-07-2019 - |
Pregunta
El programa C ++
#include <complex>
#include <iostream>
int main()
{
std::complex<double> z(0,2);
int n = 3;
std::cout << z * n << std::endl;
}
produce un error: no coincide con & # 8216; operador * & # 8217; en & # 8216; z * n & # 8217 ;. ¿Por qué?
Estoy compilando con g ++ 4.4.1. Quizás el compilador solo sigue el estándar C ++, en cuyo caso mi pregunta es: ¿por qué el estándar no permite esto?
Solución
Esto funciona:
#include <complex>
#include <iostream>
int main()
{
std::complex<double> z(0,2);
double n = 3.0; // Note, double
std::cout << z * n << std::endl;
}
Debido a que el complejo está compuesto de dobles, se multiplica por dobles. Mirando la declaración:
template <typename T>
inline complex<T> operator*(const complex<T>&, const T&);
(Lo siguiente es gracias a dribeas ) El compilador no puede realizar conversiones de tipos implícitas durante la deducción de plantillas, por lo que pasando un complejo
con T siendo doble
, y luego otro T siendo int
, al intentar hacer coincidir la función que trata T como double
hace que el segundo argumento no coincida, y viceversa.
Para lo que quiere trabajar, debería tener una función definida similar a esta:
template <typename T, typename U>
inline std::complex<T> operator*(std::complex<T> lhs, const U& rhs)
{
return lhs *= rhs;
}
Lo que permite que la función tome diferentes tipos, lo que permite realizar la conversión al llamar al operator * =
.
Otros consejos
std :: complex < T >
están definidos para tomar como argumentos otras instancias de complex < T >
. La ruta desde un int
a través de un double
a un complex < double >
es marginalmente demasiado retorcida / enrevesada para que el lenguaje C ++ la siga de acuerdo según el estándar (y con las enormes complicaciones que ya surgen de las conversiones y las coerciones de rueda libre, es difícil criticar ese aspecto del estándar). Supongo que el caso súper especial de complex < double >
que permite int
s no emitidos como operandos para sus operadores simplemente no se consideró frecuente e importante como para garantizar la especificación de especializaciones de plantilla para eso caso extremadamente individual, considerando cuán trivialmente fácil es para el programador lanzar el int
al double
cuando eso es lo que realmente quieren ! -)