Pergunta

Eu tenho uma classe, definida em uma cabeça como:

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

Em um arquivo de implementação, eu tenho:

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

Que todos os olhares bastante kosher. No entanto, quando tento usar esse operador (ou seja, std :: cout << MyClass ()), eu recebo o seguinte erro vinculador:

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

Estou surpreso o compilador não automagicially gerado isso para mim ... Qualquer sugestões sobre o que estou fazendo de errado?

Foi útil?

Solução

Em um arquivo de implementação, eu tenho:

Esse é o problema. Você não pode dividir definições de modelo entre arquivos de cabeçalho e implementação. Devido à natureza de modelos, compiladores C ++ são mimado aqui. Defina todo o código no cabeçalho para fazer o trabalho.

Na verdade, o problema aqui é que todas as definições de modelo deve residir na mesma unidade de compilação porque o C ++ padrão não define como informações do modelo são compartilhados entre diferentes unidades. Estas unidades são costuradas pelo vinculador, mas os genéricos são resolvidos em tempo de compilação (que é mais cedo), não em tempo de ligação.

Teoricamente, o C ++ padrão define uma palavra-chave, export, para lidar com esses casos. Na prática, não implementos compilador isso (com uma exceção?), E não há nenhuma intenção de mudar isso porque o custo / utilidade trade-off não é considerado bom o suficiente.

Outras dicas

demasiado muitos modelos - isso funciona:

#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;
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top