2010-07-15 3 views
4

Je suis légèrement confus avec la spécialisation de modèle. J'ai les classes Vector2, Vector3 qui ont operator+= (qui sont définies de la manière suivante).Question de modèle de base C++

Vector2& operator+=(const Vector2& v) { 

     x() += v.x(), y() += v.y(); 

     return *this; 
    } 

Maintenant, je veux ajouter le comportement de plus générique et dire quelque chose comme:

template <typename V> const V operator+(const V& v1, const V& v2) { 
    return V(v1) += v2; 
} 

Cette compile bien et fonctionne à la fois Vector2 et Vector3. Mais disons que je veux avoir un peu plus efficace opération « + » pour mon Vector2 et je veux d'agir de la manière suivante (en utilisant la spécialisation du modèle):

template<> const Vector2 operator+(const Vector2& v1, const Vector2& v2) { 
    return Vector2(v1.x() + v2.x(), v1.y() + v2.y()); 
} 

Cela semble bien pour moi, mais malheureusement placer ces deux morceaux de code juste après l'autre rend le code échouer la compilation

(linker dit erreur LNK2005: "Vector2 const operator+<Vector2>(Vector2 const &,Vector2 const &)" ([email protected]@[email protected]@@[email protected]@@[email protected]@[email protected]@Z) already defined in ...)

Quel est mon erreur et d Je vais mal?

Merci.

Répondre

7

Si la spécialisation est dans un fichier d'en-tête, vous devez le déclarer inline pour lui permettre d'être inclus dans plusieurs unités de compilation.

Notez que vous n'avez pas réellement besoin d'une spécialisation de modèle ici; une simple surcharge fera la même chose.

+2

Une surcharge serait toujours une meilleure alternative. –

3

mis cette

template<> const Vector2 operator+(const Vector2& v1, const Vector2& v2); 

dans votre fichier d'en-tête et

template<> const Vector2 operator+(const Vector2& v1, const Vector2& v2) { 
    return Vector2(v1.x() + v2.x(), v1.y() + v2.y()); 
} 

dans un fichier .cpp .

+0

Cela risque d'être moins efficace que de le définir en ligne dans le fichier d'en-tête. –

3

Je ne suis pas vraiment sûr de vouloir suivre ce chemin. Le operator+ que vous avez défini en tant que modèle correspondra à tous les types, en créant éventuellement des conflits. Pourquoi ne fournissez-vous pas un simple operator+ non-template pour chacun de vos vecteurs?

Il y a aussi d'autres questions de style:

Vector2& operator+=(const Vector2& v) { 
    x() += v.x(); // you don't need operator, here and it might 
       // be confusing if you don't have operator, priorities clear 
    y() += v.y(); 
    return *this; 
} 

aussi:

// This should not be a template!!! 
template <typename V> const V operator+(V v1, const V& v2) { 
    return v1 += v2; 
} 

Dans certaines circonstances, le compilateur peut elide la copie si operator+ est défini comme ci-dessus (si le premier argument est temporaire), alors qu'il ne peut pas élider la copie avec votre définition.

Le problème avec l'operator+ que vous avez défini est que le compilateur essaiera de l'utiliser avec tout type :

struct non_sumable {}; 
int main() { 
    non_sumable a,b; 
    a + b;   // matches the template, tries to instantiate 
        // compiler error says that non_sumable does not 
        // have operator+=, which might be confusing 
}