web-dev-qa-db-fra.com

Que signifie «utiliser ODR» quelque chose?

Cela vient d'arriver dans le contexte de ne autre question .

Apparemment, les fonctions membres des modèles de classe ne sont instanciées que si elles sont utilisées par ODR. Quelqu'un pourrait-il expliquer ce que cela signifie exactement? Le article de wikipedia sur la règle de définition unique (ODR) ne mentionne pas " ODR-use ".

Cependant, la norme le définit comme

Une variable dont le nom apparaît comme une expression potentiellement évaluée est utilisée par odr sauf s'il s'agit d'un objet qui satisfait aux exigences d'apparition dans une expression constante (5.19 ) et la conversion lvalue-to-rvalue (4.1) est immédiatement appliquée.

dans [basic.def.odr].

Edit: Apparemment, c'est la mauvaise partie et le paragraphe entier contient plusieurs définitions pour différentes choses. Cela peut être celui qui convient à la fonction membre du modèle de classe:

Une fonction non surchargée dont le nom apparaît comme une expression potentiellement évaluée ou un membre d'un ensemble de fonctions candidates, si elle est sélectionnée par la résolution de surcharge lorsqu'elle est référencée à partir d'une expression potentiellement évaluée, est utilisée par odr, sauf s'il s'agit d'un pur virtuel et son nom n'est pas explicitement qualifié.

Je ne comprends cependant pas comment cette règle fonctionne sur plusieurs unités de compilation? Toutes les fonctions membres sont-elles instanciées si j'instancie explicitement un modèle de classe?

77
Sarien

Il s'agit simplement d'une définition arbitraire, utilisée par la norme pour spécifier quand vous devez fournir une définition pour une entité (par opposition à une simple déclaration). La norme ne dit pas seulement "utilisé", car cela peut être interprété de manière diverse selon le contexte. Et certaines utilisations ODR ne correspondent pas vraiment à ce que l'on associerait normalement à "utiliser"; par exemple, une fonction virtuelle est toujours utilisée par ODR à moins qu'elle ne soit pure, même si elle n'est en fait appelée nulle part dans le programme.

La définition complète se trouve dans §3.2 , deuxième paragraphe, bien que cela contienne des références à d'autres sections pour compléter la définition.

En ce qui concerne les modèles, l'ODR utilisé n'est qu'une partie de la question; l'autre partie est l'instanciation. En particulier, le §14.7 couvre quand un modèle est instancié. Mais les deux sont liés: bien que le texte du §14.7.1 (instanciation implicite) soit assez long, le principe de base est qu'un modèle ne sera instancié que s'il est utilisé, et dans ce contexte, utilisé signifie ODR utilisé. Ainsi, une fonction membre d'un modèle de classe ne sera instanciée que si elle est appelée, ou si elle est virtuelle et que la classe elle-même est instanciée. La norme elle-même compte sur de nombreux points: le std::list<>::sort les usages < sur les éléments individuels, mais vous pouvez instancier une liste sur un type d'élément qui ne prend pas en charge <, tant que vous n'appelez pas sort dessus.

61
James Kanze

En clair, odr-used signifie que quelque chose (variable ou fonction) est utilisé dans un contexte où sa définition doit être présente.

par exemple.,

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

Remarque, le Push_back ci-dessus passé dans MSVC 2013, ce comportement n'est pas la conformité standard, gcc 4.8.2 et clang 3.8.0 ont échoué, le message d'erreur est: référence non définie à `K :: g_x '

15
zhaorufei