É código objeto gerado para métodos de classe de modelo não utilizados?
Pergunta
Eu tenho uma classe C ++ modelo que é instanciado com 3 parâmetros de tipo diferentes. Há um método que as necessidades da classe para ter apenas um desses tipos e que não é sempre chamado com os outros dois tipos.
código objeto irá para esse método ser gerados três vezes (para todos os tipos para os quais o modelo é instanciado), ou é o código objeto gerado apenas uma vez (para o tipo com o qual ele é realmente usada)?
Solução
funções membro virtuais são instanciado quando um modelo de classe é instanciado, mas as funções de membro não-virtuais são instanciado somente se eles são chamados.
Este é coberto em [temp.inst] no C ++ padrão (Em C ++ 11, este é §14.7.1 / 10. Em C ++ 14, é §14.7.1 / 11, e em C ++ 17 é §17.7.1 / 9. Extracto de C ++ 17 abaixo)
Uma implementação não deve instanciar implicitamente um modelo de função, um modelo variável, um membro modelo, uma função não-virtual membro, uma classe membro, um membro de dados estáticos de um modelo de classe, ou um subinstrução de um
constexpr
if (9.4.1), a menos que tal instanciação é necessária
Observe também que é possível instanciar um modelo de classe, mesmo se algumas das funções de membros não são instanciáveis ??para os parâmetros do modelo dado. Por exemplo:
template <class T>
class Xyzzy
{
public:
void CallFoo() { t.foo(); } // Invoke T::foo()
void CallBar() { t.bar(); } // Invoke T::bar()
private:
T t;
};
class FooBar
{
public:
void foo() { ... }
void bar() { ... }
};
class BarOnly
{
public:
void bar() { ... }
};
int main(int argc, const char** argv)
{
Xyzzy<FooBar> foobar; // Xyzzy<FooBar> is instantiated
Xyzzy<BarOnly> baronly; // Xyzzy<BarOnly> is instantiated
foobar.CallFoo(); // Calls FooBar::foo()
foobar.CallBar(); // Calls FooBar::bar()
baronly.CallBar(); // Calls BarOnly::bar()
return 0;
}
Isso é válido, embora Xyzzy :: CallFoo () não é instanciável porque não existe tal coisa como BarOnly :: foo (). Este recurso é usado frequentemente como uma ferramenta de modelo metaprogramming.
Note, no entanto, que "instanciação" de um modelo não diretamente correlato para a quantidade de código objeto é gerado. Isso vai depender de seu compilador implementação / vinculador.
Outras dicas
Eu acho que depende do compilador e configurações. Por exemplo, eu acredito MSVC6 gerado tudo, mas VS2005 não. A especificação diz o compilador não deveria, mas no mundo real, que depende do compilador real (há muitas soluções alternativas em impulso para MSVC6, por exemplo). O ligador pode remover funções não referenciadas se / opt: Ref. Estiver ativada (para VS, existem opções equivalentes para outros compiladores)
Normalmente, sim.
Todo o compilador realmente sabe é que seu programa pode criar pelo menos uma instância de cada classe. Mas não sei o que você vai fazer com essas instâncias. Assim, o código será quase certo ser gerado.
Dito isto, se os métodos em questão são não virtual, e nunca são chamados, a vinculador pode removê-los com as suas características de remoção de código morto normais. Assim, o código gerado (e compilados) não estará no EXE final.
Além disso, este dependerá em grande parte o compilador C ++ sendo usado, porque eles não são todos iguais.