2013-07-26 1 views
2
template <class T> 
class Foo { 
public: 
    T val; 
    Foo(T _v): val(_v){} 
    friend ostream& operator<< (ostream& out, const Foo& A) { 
     out << A.val; 
     return out; 
    } 
}; 

template <class X, class Y> Foo<???> operator+(const Foo<X>& A, const Foo<Y> & B) { 
    if (sizeof(X) > sizeof (Y)) 
     return Foo<X>(A.val + B.val); 
    else 
     return Foo<Y>(A.val + B.val); 
} 

int main() { 
    Foo<double> a(1.5); 
    Foo<int> b(2); 
    cout << a << endl; 
    cout << b << endl; 
    cout << a+b << endl; 
} 

Mon objectif est que la fonction operator+ renvoie un type différent en fonction des types d'arguments.promotion de type automatique de modèle C++

Par exemple, si a est int et b est int puis revenir Foo<int>, si un ou les deux d'entre eux sont double puis revenez Foo<double>.

Est-il possible de faire?

+1

En réponse aux commentaires ci-dessous, j'ai ajouté le tag C++ 03. Lorsque vous suivez une version non actuelle de quelque chose, vous devriez l'indiquer dans vos questions. –

Répondre

3

Ceci est possible (en 03 ou 11 C++ C +) en utilisant les spécialisations de modèle partiel.

// C++ does not allow partial specialization of function templates, 
// so we're using a class template here. 

template <typename X, typename Y, bool xLarger> 
struct DoPlusImpl // When x is selected 
{ 
    typedef Foo<X> result_type; 
}; 

template <typename X, typename Y> 
struct DoPlusImpl<X, Y, false> // When y is selected 
{ 
    typedef Foo<Y> result_type; 
}; 

template <typename X, typename Y> // Select X or Y based on their size. 
struct DoPlus : public DoPlusImpl<X, Y, (sizeof (X) > sizeof (Y))> 
{}; 

// Use template metafunction "DoPlus" to figure out what the type should be. 
// (Note no runtime check of sizes, even in nonoptimized builds!) 
template <class X, class Y> 
typename DoPlus<X, Y>::result_type operator+(const Foo<X>& A, const Foo<Y> & B) { 
    return typename DoPlus<X, Y>::result_type 
     (A.val + B.val); 
} 

Vous pouvez le voir en action sur IDEOne ici ->http://ideone.com/5YE3dg

+0

'Erreur: ISO C++ interdit la déclaration de 'opérateur +' sans type [-fpermissive]' Est-ce que 'auto' est une fonctionnalité de C++ 11? –

+0

@Tran: J'ai confirmé que ceci est valide - le retour final n'est nécessaire que pour certains types de scénarios decltype. Cela devrait faire ce que vous voulez. –

+0

@Tran: Ajout d'un exemple IDEOne fonctionnant avec votre classe d'échantillon. –

4

(11 C++): utiliser une expression declval intérieur dectype:

#include <utility> 

template <class X, class Y> 
Foo<decltype(std::declval<X>() + std::declval<Y>())> operator+(...); 
+0

Le compilateur dit: ''common_type' 'dans l'espace de noms' std 'ne nomme pas un type' et' error: l'argument template 1 est invalide' –

+0

@TranSonHai J'ai fait un edit. S'il vous plaît voir – 0x499602D2

+0

Cette fois, il dit 'erreur: 'declval' n'est pas un membre de 'std' et 'error: template argument 1 est invalide' –

1

Oui! Voici la façon si vous voulez donner vos propres règles:

template <typename X, typename Y> struct Rule {}; 
template<> struct Rule<int, int> { typedef int type;}; 
template<> struct Rule<float, int> { typedef bool type;}; 

Puis

template <class X, class Y> Foo<typename Rule<X, Y>::type> operator+(...) 
+0

Pourriez-vous le rendre plus générique ?, Foo pourrait prendre non seulement int, double, float mais tout un tas de types différents, faites-le à votre façon se traduira par n^2 combinaisons possibles. –

+0

Cela ne fonctionne pas à moins que l'OP connaisse l'univers de tous les types X et Y, et exige que l'OP fournisse des spécialisations explicites pour les inversions. (Autrement dit, il faut définir une spécialisation explicite pour '' et '') On peut supposer que l'OP ne sait pas quelles sont toutes les valeurs de 'X' et' Y'. –

Questions connexes