Pergunta

Suponha que um arquivo de cabeçalho define um modelo de função. Agora, dois arquivos de implementação suponha #include este cabeçalho, e cada um deles tem uma chamada para o modelo de função. Em ambos implementação arquiva o modelo de função é instanciado com o mesmo tipo.

// header.hh
template <typename T>
void f(const T& o)
{
    // ...
}

// impl1.cc
#include "header.hh"

void fimpl1()
{
    f(42);
}

// impl2.cc
#include "header.hh"

void fimpl2()
{
    f(24);
}

Pode-se esperar que o vinculador iria reclamar sobre várias definições de f(). Especificamente, se f() não seria um modelo, então, que seria de fato o caso.

  • Como é que o vinculador não reclamar várias definições de f()?
  • É especificado no padrão que o vinculador deve lidar com esta situação graciosamente? Em outras palavras, eu posso sempre contar com programas similares ao acima para compilar e link?
  • Se o ligador pode ser o suficiente inteligente para disambiguate um conjunto de funções instâncias de modelo, porque ele não pode fazer o mesmo para funções regulares, uma vez que eles são idênticos, como é o caso de modelos de função instanciado?
Foi útil?

Solução

A fim de apoiar C ++, o vinculador é inteligente o suficiente para reconhecer que eles são todos a mesma função e joga fora todos menos um.

EDIT: Esclarecimento: O vinculador não comparar conteúdos de função e determinar que eles são os mesmos. funções Templated são marcadas como tal e o vinculador reconhece que eles têm as mesmas assinaturas.

Outras dicas

manual do compilador GNU C ++ tem uma boa discussão deste . Um trecho:

modelos C ++ são a primeira língua apresentam a exigir mais inteligência a partir do ambiente do que um normalmente encontra em um sistema UNIX. De alguma forma o compilador e vinculador tem que ter certeza que cada instância do molde ocorre exatamente uma vez no executável se é necessário, e não em tudo o contrário. Existem duas abordagens básicas para esta problema, que são referidos como a Borland modelo eo modelo Cfront.

modelo Borland

Borland C ++ resolvido o modelo problema instanciação adicionando o código equivalente de blocos comuns aos sua vinculador; os emite compilador exemplos de modelo em cada tradução unidade que usa-los, e o ligador desmorona-los juntos. A vantagem deste modelo é que o vinculador única tem de considerar os arquivos objeto si mesmos; não há externa complexidade com que se preocupar. este desvantagem é que o tempo de compilação é aumentada porque o código do modelo está sendo compilado repetidamente. Código escrito para este modelo tende a incluem definições de todos os modelos no cabeçalho do arquivo, uma vez que deve ser visto para ser instanciado.

Cfront modelo

A AT & T C ++ tradutor, Cfront, resolveu o instanciação de modelo problema criando a noção de um repositório de modelos, um automaticamente lugar mantido onde template casos são armazenados. A mais moderna versão do repositório funciona como seguinte maneira: Como arquivos de objetos individuais são construídos, o compilador coloca qualquer definições de modelo e instantiations encontradas no repositório. Em tempo de link, o link envoltório acrescenta os objetos no repositório e compila qualquer necessária instâncias que não eram previamente emitida. As vantagens deste modelo são mais velocidade óptima e compilação a capacidade para utilizar o sistema de ligante; para implementar o Borland modelo de um fornecedor compilador também precisa de substituir vinculador. As desvantagens são muito maior complexidade, e assim potencial de erro; para algum código isso pode ser tão transparente, mas na prática, pode ser muito difícil a programas de construção múltiplas em um diretório e um programa em múltiplos diretórios. O código escrito para este modelo tende a definições separadas de modelos de membros não-incorporadas em um arquivo separado, que deve ser compilados separadamente.

Quando usado com GNU versão 2.8 ou ld mais tarde em um sistema ELF como GNU / Linux ou Solaris 2, ou em Microsoft Windows, G ++ suporta a modelo Borland. Em outros sistemas, G ++ implementos nem modelo automático.

Este é mais ou menos um caso especial apenas para modelos.

O compilador só gera as instâncias de modelo que são realmente utilizados. Uma vez que não tem controle sobre o que o código será gerado a partir de outros arquivos de origem, tem que gerar o código do modelo, uma vez para cada arquivo, para se certificar de que o método é gerada em tudo.

Uma vez que é difícil de resolver isso (o padrão tem uma palavra-chave extern para modelos, mas g ++ não implementá-lo) o ligador simplesmente aceita as várias definições.

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