Estoy tratando de construir una clase num con plantilla. Esta clase debe tener un atributo público val
, con tipo T
, que es el único parámetro con plantilla. Además, si uno proporciona un valor, el atributo ( val
) debe inicializarse con este valor. Para hacerlo hice el siguiente código:
#include <iostream>
template<class T>
class Num {
public:
T val;
Num():val(0) { std::cout<<"default constr used"<<std::endl; }
Num(T value):val(value) {std::cout<<"constr (T value) used"<<std::endl; }
~Num() { std::cout<<"destructor used"<<std::endl; }
template<typename U>
Num operator+(const Num<U>& other) {
return val+other.value;
}
};
Además, creé la main()
función para probar el programa, que se ve así:
int main() {
std::cout << Num<int>(1) + Num<double>(2.0);
return 0;
}
Sin embargo, el resultado del programa es ahora 3
. Mientras que esperaba que fuera 3.0
(de tipo double
).
c++
class
templates
operator-overloading
Racicot Guillaume
fuente
fuente
Num<int>(1) + Num<double>(2.0);
es lo mismoNum<int>(1).operator+(Num<double>(2.0))
que has declarado que devuelve un valor de tipoNum<int>
.value
.Respuestas:
Para eso necesitarás cambiar el tipo de retorno.
En su código:
De hecho, dentro de una plantilla de clase, puede escribir el nombre de la clase sin argumentos de plantilla y será algo equivalente a escribir
Num<T>
.Su función siempre devuelve el tipo de la primera operante, sin importar el tipo de la suma en sí.
Lo que quieres es deducir ese tipo a partir de la adición:
De esa manera, siempre es el tipo de retorno correcto de acuerdo con las reglas del operador de C ++.
fuente
-> Num<decltype(val + other.val)>
decltype(val + other.val)
, y noNum<decltype(val + other.val)>
.Num{val + other.val}
operator+
debe ser simétrico con respecto a sus argumentos. Es mejor implementarlo como una función libre en lugar de una función miembro para hacer explícita esta simetría.Por ejemplo (usando la deducción de tipo de retorno C ++ 14):
std::declval<T>()
está ahí para el carácter genérico , siT
y / oU
no son construibles por defecto. Si los tipos se limitan a los incorporados, comoint
ydouble
, se puede reemplazar conT{}
oT()
:Con la deducción de argumentos de plantilla de clase en C ++ 17 se puede simplificar aún más:
fuente
auto
eliminar un tipo de devolución. Esto está muy bien.