Question

I ai une classe, définie dans une tête en tant que:

template <typename T> class MyClass
{
   template <typename U> friend std::ostream& operator<<(std::ostream& output, const MyClass<U>& p);
   public:
      ...
}

Dans un fichier de mise en œuvre, je:

template <typename U> std::ostream& operator<<(std::ostream& output, const MyClass<U>& m)
{
   output << "Some stuff";
   return output;
}

Ce qui tout semble assez casher. Cependant, quand j'essaie d'utiliser cet opérateur (par exemple std :: Cout << MyClass ()), je reçois l'erreur de liens suivant:

Undefined symbols: std::basic_ostream<char, std::char_traits<char> >& operator<< <InnerType>(std::basic_ostream<char, std::char_traits<char> >&, MyClass<InnerType> const&)

Je suis surpris que le compilateur n'a pas automagicially généré pour moi ... Des suggestions quant à ce que je fais mal?

Était-ce utile?

La solution

  

Dans un fichier de mise en œuvre, je:

C'est le problème. Vous ne pouvez pas diviser définitions modèle entre les fichiers d'en-tête et la mise en œuvre. En raison de la nature des modèles, les compilateurs C sont de tatillonne ici. Définir tout le code dans l'en-tête pour le faire fonctionner.

En fait, le problème est que toutes les définitions de modèle doivent résider dans la même unité de compilation parce que la norme C de ne définit pas comment les informations du modèle sont partagées entre différentes unités. Ces unités sont cousues ensemble par l'éditeur de liens, mais génériques sont résolus au moment de la compilation (qui est plus haut), pas au moment de lien.

En théorie, la norme C ++ définit un mot-clé, export, pour traiter ces cas. Dans la pratique, pas compilateur implémente cette (à une exception près?), Et il n'y a pas l'intention de changer cela parce que le rapport coût / utilité compromis n'est pas considéré comme assez bon.

Autres conseils

Trop de modèles - cela fonctionne:

#include <iostream>
using namespace std;
template <typename T> struct MyClass {

    friend ostream & operator << ( ostream & os, MyClass<T> & c ) {
        os << "MyClass\n";
        return os;
    }
};

int main() {
    MyClass <int> c;
    cout << c;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top