Isso acabou de surgir no contexto de outra questão .
Aparentemente, funções de membro em modelos de classe são instanciadas apenas se forem usadas por ODR. Alguém poderia explicar o que exatamente isso significa. O artigo da Wikipedia sobre One Definition Rule (ODR) não menciona o " uso de ODR ".
No entanto, o padrão o define como
Uma variável cujo nome aparece como uma expressão potencialmente avaliada é usada por odr, a menos que seja um objeto que satisfaça os requisitos para aparecer em uma expressão constante (5.19) e a conversão de lvalor em rvalue (4.1) seja aplicada imediatamente.
em [basic.def.odr].
Edit: Aparentemente, esta é a parte errada e todo o parágrafo contém várias definições para coisas diferentes. Este pode ser relevante para a função de membro do modelo de classe:
Uma função não sobrecarregada cujo nome aparece como uma expressão potencialmente avaliada ou um membro de um conjunto de funções candidatas, se selecionada por resolução de sobrecarga quando referida a partir de uma expressão potencialmente avaliada, é usada por odr, a menos que seja um virtual puro função e seu nome não é explicitamente qualificado.
No entanto, não entendo como essa regra funciona em várias unidades de compilação. Todas as funções de membro são instanciadas se eu explicitamente instanciar um modelo de classe?
fonte
Respostas:
É apenas uma definição arbitrária, usada pelo padrão para especificar quando você deve fornecer uma definição para uma entidade (em oposição a apenas uma declaração). O padrão não diz apenas "usado", porque isso pode ser interpretado de forma diversa dependendo do contexto. E algum uso de ODR realmente não corresponde ao que normalmente associaríamos com "uso"; por exemplo, uma função virtual é sempre usada pelo ODR, a menos que seja pura, mesmo que não seja realmente chamada em nenhum lugar do programa.
A definição completa está em §3.2 , segundo parágrafo, embora contenha referências a outras seções para completar a definição.
Com relação aos modelos, o uso do ODR é apenas parte da questão; a outra parte é a instanciação. Em particular, §14.7 cobre quando um modelo é instanciado. Mas os dois estão relacionados: enquanto o texto em §14.7.1 (instanciação implícita) é bastante longo, o princípio básico é que um modelo só será instanciado se for usado e, neste contexto, usado significa usado pelo ODR. Portanto, uma função de membro de um modelo de classe só será instanciada se for chamada ou se for virtual e a própria classe for instanciada. O próprio padrão conta com isso em muitos lugares: o
std::list<>::sort
usa<
nos elementos individuais, mas você pode instanciar uma lista sobre um tipo de elemento que não suporta<
, desde que você não o chamesort
.fonte
Em palavras simples, odr-used significa que algo (variável ou função) é usado em um contexto onde a definição deve estar presente.
por exemplo,
struct F { static const int g_x = 2; }; int g_x_plus_1 = F::g_x + 1; // in this context, only the value of g_x is needed. // so it's OK without the definition of g_x vector<int> vi; vi.push_back( F::g_x ); // Error, this is odr-used, push_back(const int & t) expect // a const lvalue, so it's definition must be present
Observe que o push_back acima foi aprovado no MSVC 2013, este comportamento não é compatível com o padrão, gcc 4.8.2 e clang 3.8.0 falharam, a mensagem de erro é: referência indefinida para `K :: g_x '
fonte
vi.push_back( F::g_x );
em c ++?const int&
? O membro const estático pode ser ragarded como rvalue?push_back
, é claro que vai passar. Não é?operator+
.