2013-06-23 7 views
7

Ho una classe template definita come questol'overloading degli operatori al di fuori di una classe modello con conversioni implicite

template<class T> class Wrap 
{ 
    /* ... */ 
public: 
    Wrap(const T&); 
    /* other implicit conversions */ 

    /* ... */ 
}; 

voglio definire tutti gli operatori di confronto per questa classe di fuori della classe come questo

template<typename T> bool operator == (const Wrap<T>&, const Wrap<T>&) 
{ 
    // Do comparison here 
} 

Tuttavia, questa dichiarazione non supporta le conversioni implicite di const T& o di qualsiasi altro tipo su const Wrap<T>&.

Quindi la mia domanda è: come posso far sì che sostenga le conversioni implicite quando uno degli operandi è di tipo Wrap<T> e l'altro no. Non voglio scrivere più dichiarazioni di ogni operatore per ogni permutazione possibile.

risposta

4
template<class T> struct is_wrap : std::false_type {}; 
template<class T> struct is_wrap<Wrap<T>> : std::true_type {}; 

template<class T1, class T2> typename std::enable_if<is_wrap<typename std::common_type<T1, T2>::type>::value, bool>::type operator == (const T1& t1, const T2& t2) 
{ 
    const typename std::common_type<T1, T2>::type& tc1 = t1, tc2 = t2; 
    // compare with tc1 and tc2 
} 
+0

Ottima risposta. Suppongo che tu abbia perso il riferimento per 'tc2'. – user1353535

1

Qualcun altro lo articolerà meglio, ma penso che il problema è che il compilatore non può dedurre T in Wrap<T> senza passare un oggetto Wrap. Penso che la tua situazione dovrebbe essere risolta se esprimi esplicitamente l'argomento modello: operator==<int>(7, 4), ad esempio dovrebbe funzionare.

Non ho un compilatore di fronte a me, ma qui è la mia prova:

template<typename T> 
typename std::enable_if<std::is_convertible<Wrap<T>, T>::value, bool>::type operator==(const Wrap<T>& l, const T& r) 
{ 
    return l.stuff == Wrap<T>(r).stuff; 
} 

template<typename T> 
typename std::enable_if<std::is_convertible<Wrap<T>, T>::value, bool>::type operator==(const T& l, const Wrap<T>& r) 
{ 
    return r == l; // call above operator 
} 

Questo dovrebbe funzionare se entrambi i lati è un Wrap e l'altro lato non è. Si potrebbe anche fare entrambe le parti come const T&, se Wrap è davvero implicitamente costruibile da qualsiasi T sarà vento usando il tuo operator== per molti paragoni non intenzionali, anche di int s, string s, ecc

+0

Questo richiede ancora ho aggiunto altre 2 dichiarazioni per ogni operatore che volevo evitare. – user1353535