Pergunta

Eu tenho muito pouca idéia do que está acontecendo em relação aos modelos C ++, mas eu estou tentando implementar uma função que procuras um vetor para um elemento satisfazer uma determinada propriedade (neste caso, em busca de um com o nome dado). Minha declaração no meu arquivo .h é a seguinte:

template <typename T>
T* find_name(std::vector<T*> v, std::string name);

Quando eu compilar, eu recebo este erro vinculador quando eu chamar a função:

Error   1   error LNK2019: unresolved external symbol "class Item * __cdecl find_name<class Item>(class std::vector<class Item *,class std::allocator<class Item *> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (??$find_name@VItem@@@@YAPAVItem@@V?$vector@PAVItem@@V?$allocator@PAVItem@@@std@@@std@@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z) referenced in function "public: class Item * __thiscall Place::get_item(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?get_item@Place@@QAEPAVItem@@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) place.obj   Program2

Novamente, eu sou novo para modelos, então eu não sei o que está acontecendo. Todos os casos que eu encontrei de LNK2019 através do Google ter sido sobre não usar as bibliotecas corretas, mas já que esta é a minha própria função não vejo por que isso estaria acontecendo.

Além disso, uma questão relacionada: Existe uma maneira de fazer um parâmetro de modelo para que ele tem que ser uma subclasse de uma certa classe, ou seja, template

?
Foi útil?

Solução

Você tem que ter as suas definições de modelo disponível no site chamado. Isso significa que nenhum arquivo .cpp.

A razão é modelos não podem ser compilado. Pense funciona como cookies, eo compilador é um forno.

Modelos são apenas um cortador de biscoitos, porque eles não sabem o tipo de cookie que são. Ele só diz ao compilador como fazer a função quando dado um tipo, mas em si mesmo, não pode ser usado porque não há nenhum tipo de concreto que está sendo operado. Você não pode cozinhar um cortador de biscoitos. Somente quando você tem o cookie saborosa massa pronta (ou seja, dado o compilador a massa [tipo])) você também pode cortar o cookie e cozinhá-lo.

Da mesma forma, somente quando você realmente usar o modelo com um certo tipo pode o compilador gerar a função real, e compilá-lo. Ele não pode fazer isso, no entanto, se a definição do modelo está faltando. Você tem que movê-lo para o arquivo de cabeçalho, de modo que o chamador da função pode fazer o cookie.

Outras dicas

Você provavelmente estão sofrendo de perder uma instanciação válido. Se você colocar a sua definição do modelo em um arquivo .cpp separado, quando os compila compilador esse arquivo pode não saber qual instantiations você precisa. Por outro lado, nos locais de atendimento que instanciar a versão correta da função de modelo, se a definição do corpo da função não está disponível o compilador não terá as informações para instanciar as especializações necessárias.

Você tem duas opções. Coloque o corpo da função para o modelo de função no cabeçalho do arquivo.

por exemplo. no cabeçalho do arquivo:

template <typename T>
inline T* find_name(std::vector<T*> v, std::string name)
{
    // ...
}

ou instanciar explicitamente o modelo no .cpp onde você definiu o modelo.

por exemplo. no arquivo de origem (provavelmente exigirá #includeing o arquivo que define Item):

template <typename T>
T* find_name(std::vector<T*> v, std::string name)
{
    // ...
}

template Item* find_name<Item>(std::vector<Item*> v, std::string name);

As respostas aqui são grandes.

Vou apenas acrescentar que esta é muitas vezes porque além de arquivos .h e .cpp em um projeto. Muitas vezes você vai encontrar arquivos .inl. As definições de modelo irá para o arquivo .inl.

Estes .inl arquivos em linha média e geralmente será incluído pelo arquivo .h de mesmo nome prefixo na parte inferior do arquivo depois de todas as declarações de cabeçalho. Isso efetivamente torna parte do arquivo de cabeçalho, mas separa as declarações de quaisquer definições.

Uma vez que eles são arquivos de cabeçalho glorificados você deve tomar todas as mesmas precauções que você faria com um arquivo de cabeçalho regular, ou seja, incluem guardas etc.

Tropeçamos mediante o mesmo problema e encontrei este que afirma 3 soluções: http: / /www.codeproject.com/Articles/48575/How-to-define-a-template-class-in-ah-file-and-imp

Entre eles é fácil, onde você criar um método "fictício" no arquivo .cpp, que chama a função template / classe com os diferentes tipos. Colado a partir do link:

// No need to call this TemporaryFunction() function, it's just to avoid link error.
void TemporaryFunction ()
{
    TestTemp<int> TempObj;
    TestTemp<float> TempObj2;
}

Eu notei que você tinha uma segunda pergunta que parece ser sem resposta:

Existe uma maneira de fazer um parâmetro de modelo para que ele tem que ser uma subclasse de uma certa classe, ou seja, modelo?

É possível. Por exemplo, veja is_base_of em Boost.TypeTraits .

No entanto, estou curioso: Por que você quer isso? Normalmente, as exigências de um modelo em seus parâmetros não são em si mesmo o tipo do parâmetro, mas em que expressões envolvendo esse tipo são legais. Por exemplo, imagine que você tem:

template<class T>
void foo(const T& t)
{
    if (t.foo()){
       t.bar("blah");
    }
}

Dizer que T deve herdar algo como:

class HasFooAndBar
{
public:
  void foo()const;
  void bar(const char*)const;
};

não traz nada porque a instanciação da função irá falhar de qualquer maneira se o tipo não suporta as operações. Além disso, desnecessariamente restringe a aplicabilidade da foo(). Na verdade, foo é quaisquer requisitos são que t.foo() and t.bar(const char*) são expressões válidas em um const T. Por exemplo, este tipo não herda de HasFooAndBar e ainda é um foo válido () parâmetro:

struct DifferentFromHasFooAndBar
{
  bool foo()const;
  std::string bar(const std::string&)const;
};

Será que você colocar a sua definição função de modelo em um arquivo cpp? Em seguida, movê-lo para o cabeçalho e inline.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top