2015-10-24 17 views
5

Se ho un generico struct/classe:Come promuovere due tipi di modelli per operazioni aritmetiche come fanno i tipi built-in?

template<typename T> 
struct Container 
{ 
    T value; 
    Container(const Value& value) : value(value) { } 
}; 

E voglio eseguire un'operazione su due di loro:

template<typename T, typename U> 
Container<T> operator+(const Container<T>& lhs, const Container<U>& rhs) 
{ 
    return Container<T>(lhs.value + rhs.value); 
} 

Il problema è che se lhs è del tipo Container<int> e rhs è del tipo Container<float>, quindi ricevo un Container<int> indietro. Ma se dovessi fare auto result = 2 + 2.0f, allora result sarebbe di tipo float. Quindi il comportamento è incoerente tra tipi di build e tipi personalizzati.

Quindi, in che modo prendo il sovraccarico dello operator+ e lo restituisco Container<float>, proprio come C++ gestisce la promozione aritmetica con i tipi incorporati?

+0

si può utilizzare C++ 11? –

+0

@PiotrSkotnicki Sì. – Therhang

risposta

5

Per quanto si utilizza uno dei due tipi di modello, si rischia di indurre un cast sul risultato della somma. Ad esempio, se si sceglie accidentalmente int come tipo di destinazione, anche se la somma risulta in un float, verrà eseguito il cast verso il basso per il tipo scelto.

Comunque, iniziando con C++ 11, è con affidamento sul decltype specificatore come nell'esempio precedente (o almeno, si può fare se Container::T e Container::U sono un tipo per il quale l'operatore + è definito).

Ho utilizzato anche l'identificatore auto come valore di ritorno per lo operator+, poiché è a nostra disposizione a partire da C++ 14 ed è davvero molto utile.

Si segue l'esempio di lavoro di cui sopra:

#include <iostream> 
#include <vector> 

template<typename T> 
struct Container 
{ 
    T value; 
    Container(const T& value) : value(value) { } 
}; 

template<typename T, typename U> 
auto operator+(const Container<T>& lhs, const Container<U>& rhs) 
{ 
    return Container<decltype(lhs.value+rhs.value)>{lhs.value + rhs.value}; 
} 

int main() 
{ 
    Container<int> c1{1}; 
    Container<float> c2{0.5}; 
    std::cout << (c1+c2).value << std::endl; 
} 
+1

Sembra buono. Puoi renderlo più leggibile con una funzione helper 'make_container' che consente di dedurre l'argomento template:' return make_container (lhs.value + rhs.value); ' – hvd

+0

buon punto, lo lascerei come compito a casa ...: -) – skypjack

+0

Ci sono costi di runtime aggiuntivi aggiunti dall'operazione eseguita in 'decltype'? Sarebbe meglio se memorizzassi il risultato in una variabile temporanea 'auto' e facessi qualcosa tipo' return Container (result); '? – Therhang

Problemi correlati