O que significa “usar ODR” algo?

94

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?

Sarien
fonte
2
Observe que [basic.def.odr] / 6 se aplica a funções de membro de modelos de classe "Pode haver mais de uma definição [...]"
dyp
3
"Todas as funções de membro são instanciadas se eu explicitamente instanciar um modelo de classe?" Sim, consulte [temp.explicit] / 8 + 9
dyp

Respostas:

72

É 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<>::sortusa <nos elementos individuais, mas você pode instanciar uma lista sobre um tipo de elemento que não suporta <, desde que você não o chame sort.

James Kanze
fonte
o uso de ODR poderia se sobrepor a "temporários materializados"?
v.oddou
23

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 '

zhaorufei
fonte
É possível usar odr-um membro de dados estáticos como vi.push_back( F::g_x );em c ++?
Rankaba de
Mas um rvalue também pode ser passado para const int&? O membro const estático pode ser ragarded como rvalue?
scottxiao
8
+1 para a frase de abertura sucinta: "Em palavras simples, odr-used significa algo (variável ou função) é usado em um contexto onde a definição deve estar presente."
Paul Masri-Stone
1
Eu não entendo como você compila esse código. Eles estão na mesma TU? Se estiverem, F :: g_x já foi definido antes push_back, é claro que vai passar. Não é?
Lewis Chan
1
@bigxiao " um rvalue também pode ser passado " Sim e um objeto temporário é criado pelo compilador e a referência ligada a esse objeto. OTOH ao passar um lvalue que significa passar aquele objeto referido pela avaliação do lvalue: quando você passa um lvalue você pode esperar que o parâmetro na função se refira ao objeto correto. O compilador não criará um temporário. Se você quiser um temporário, faça um com operator+.
curioso