Estou tentando criar uma classe num modelada. Essa classe precisa ter um atributo público val
, com o tipo T
, que é o único parâmetro modelado. Além disso, se alguém fornecer um valor, o atributo ( val
) deverá ser inicializado com esse valor. Para fazer isso, criei o seguinte 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;
}
};
Além disso, criei a main()
função para testar o programa, que se parece com isso:
int main() {
std::cout << Num<int>(1) + Num<double>(2.0);
return 0;
}
No entanto, o resultado do programa é agora 3
. Considerando que eu esperava que fosse 3.0
(do tipo double
).
c++
class
templates
operator-overloading
Guillaume Racicot
fonte
fonte
Num<int>(1) + Num<double>(2.0);
é o mesmo queNum<int>(1).operator+(Num<double>(2.0))
o que você já declaradas como retornando um valor do tipoNum<int>
.value
.Respostas:
Para isso, você precisará alterar o tipo de retorno.
No seu código:
De fato, dentro de um modelo de classe, você pode digitar o nome da classe sem argumentos de modelo e será algo equivalente a escrever
Num<T>
.Sua função está sempre retornando o tipo do primeiro operante, independentemente do tipo da adição em si.
O que você deseja é deduzir esse tipo proveniente da adição:
Dessa forma, é sempre o tipo de retorno correto de acordo com as regras do operador C ++.
fonte
-> Num<decltype(val + other.val)>
decltype(val + other.val)
e nãoNum<decltype(val + other.val)>
.Num{val + other.val}
operator+
deve ser simétrico em relação a seus argumentos. É melhor ser implementado como uma função livre, em vez de uma função membro, para tornar essa simetria explícita.Por exemplo (usando a dedução de tipo de retorno C ++ 14):
std::declval<T>()
existe para genéricos , seT
e / ouU
não são construtíveis por padrão. Se os tipos forem limitados aos incorporados, comoint
edouble
, ele poderá ser substituído porT{}
ouT()
:Com a dedução de argumento do modelo de classe no C ++ 17, pode ser simplificado ainda mais:
fonte
auto
afastar um tipo de retorno. Isso é bem legal.