5
votes

Pourquoi la règle de définition unique n'est-elle pas abandonnée pour C ++ 17?

Citant le projet C ++ N4713:

Chaque programme doit contenir exactement une définition de chaque non-inline fonction ou variable utilisée par odr dans ce programme en dehors d'un déclaration rejetée (9.4.1); aucun diagnostic requis. La définition peut apparaître explicitement dans le programme, il peut être trouvé dans le standard ou une bibliothèque définie par l'utilisateur, ou (le cas échéant) il est implicitement défini (voir 15.1, 15.4 et 15.8). Une fonction ou une variable en ligne doit être défini dans chaque unité de traduction dans laquelle il est utilisé odr en dehors d'une instruction ignorée.

Dans les versions C ++ antérieures à C ++ 17, je peux contourner cette restriction en déclarant simplement mes fonctions inline . C ++ 17 ajoute la même fonctionnalité pour les variables.

De plus, il me semble que le inline -Keyword ne sert pas d'autre fin que de permettre d'ignorer l'ODR.

Alors, pourquoi toute cette règle n'est-elle pas simplement abandonnée pour C ++ 17? Je ne vois pas l'objectif d'une règle qui peut être désactivée.


7 commentaires

Parce que s'il est abandonné, que se passe-t-il lorsque vous avez un conflit de symboles avec plusieurs définitions du même élément avec une implémentation différente dans les unités de traduction?


@Ricardo Pourquoi devrait-il être abandonné?


Pourquoi voudriez-vous «contourner» une restriction qui vous protège?


Même avec le futur module, nous pouvons casser ODR: - /


Même avec inline , les sources des définitions multiples doivent être identiques, donc dans ce sens il ne peut toujours y avoir qu'une seule définition; il est simplement dupliqué dans plusieurs unités de traduction.


@ Jarod42 mais avec des modules - la violation de l'ODR devrait (c'est mon avis) être reconnue au moment de la compilation, selon open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1103r2.pdf : Une variable, une fonction, un type de classe, Le type d'énumération ou le modèle ne doit pas être défini lorsqu'une définition antérieure est accessible (100.6) . Alors peut-être que les violations ODR seront finalement des erreurs du compilateur.


@marcinj: Certaines violations ODR seraient probablement facilement détectées avec des modules, mais nous pouvons toujours casser l'ODR de tant de façons.


4 Réponses :


1
votes

Le compromis est que vous avez besoin de la définition d'une fonction inline partout où elle est utilisée. Si vous le souhaitez, mettez simplement votre programme entier dans un seul fichier .cpp.

Le ODR est ce dont vous avez besoin pour avoir une compilation séparée, et c'est toujours utile.


0 commentaires

14
votes

"Désactiver" l'ODR avec inline n'est pas gratuit: la définition d'une entité inline doit être présente dans chaque unité de traduction. Notez que cela implique que toute modification de sa définition entraîne une recompilation de chaque unité de compilation qui l'utilise. Cela serait particulièrement désagréable lorsque la fonction fait partie d'une bibliothèque dont dépendent de nombreux / gros projets.

Les fonctions

non- inline , par contre, ne vivent que dans une seule unité de compilation et sont référencées via un symbole par l'éditeur de liens lorsque cela est nécessaire ailleurs. Le respect de l'ODR garantit que le symbole n'est pas ambigu.


6 commentaires

... et cette définition doit être exactement la même dans toutes les unités de traduction.


@rustyx Vrai. Bien sûr, inline ne désactive pas vraiment l'ODR, c'est pourquoi je le mets entre guillemets. Ces détails exacts de la sémantique inline ne sont pas vraiment pertinents dans le cadre de ce Q / R de relativement haut niveau via l'OMI, donc je préférerais les ignorer par souci de concision et de clarté.


L'ODR ne garantit qu'un symbole n'est pas ambigu; il nécessite qu'il ne soit pas ambigu. Le fardeau incombe au programmeur. Les violations ODR ne doivent pas être diagnostiquées et elles entraînent un comportement indéfini. Un résultat pratique est que lorsque vous avez deux définitions différentes de la "même" fonction, vous ne savez pas laquelle sera liée.


@PeteBecker Ce serait probablement un problème de langue de ma part. J'ai essayé de le réparer.


@BaummitAugen - oui, c'est mieux. Je vais laisser mon commentaire comme une élaboration.


@PeteBecker Merci. Je pensais que la conformité était implicite, comme "Le code de la route garantit que vous pouvez traverser un feu vert en toute sécurité (à moins que quelqu'un exécute un rouge, implicitement) ". Vous apprenez quelque chose de nouveau chaque jour. :)



1
votes

De cppreference :

Une et une seule définition de chaque fonction ou variable non en ligne qui est utilisé par odr (voir ci-dessous) doit apparaître dans l'ensemble programme (y compris toutes les bibliothèques standard et définies par l'utilisateur). le le compilateur n'est pas nécessaire pour diagnostiquer cette violation, mais le comportement du programme qui le viole n'est pas défini.

Déclarer une fonction comme en ligne n'ignore pas l'ODR, mais cela fait que chaque apparence de la fonction est sa propre entité qui a besoin d'une définition dans chaque unité de traduction où elle est utilisée. Différence petite mais significative. ODR doit toujours avoir des unités de traduction séparées.


0 commentaires

4
votes

inline est dangereux et coûteux.

C'est cher car chaque unité de compilation qui utilise quelque chose dépend maintenant de la définition de la chose. Alors changez le corps? Recompilez chaque utilisateur.

C'est dangereux car si deux définitions inline ne sont pas d'accord, votre programme est IF-NDR (mal formé, aucun diagnostic requis).

Sans inline , deux définitions provoquent un programme mal formé, mais le compilateur doit fournir un diagnostic; généralement une erreur grave.

inline désactive cet avertissement extrêmement utile.

Si chaque compilateur était capable de convertir l'IF-NDR de différentes définitions inline en un message d'erreur de diagnostic, vous auriez plus d'un cas. Tant que cela s'avère difficile et / ou non implémenté, inline est un "activer le mode unsafe!" option. Le faire par défaut serait contre-productif.


1 commentaires

Pour expliquer le point de Yakk selon lequel inline est cher: si le programmeur choisit d'utiliser un inline sans profilage et évaluation du gain de performance, alors la dépense (dans tout projet de taille moyenne ou plus grande) dépasse de loin le gain de performance inconnu (le cas échéant). Et "Whole Program Optimization" (WPO) ou "Link Time Optimization" (LTO) peut rendre inutile tout gain aussi coûteux, pour les exécutables qui peuvent exploiter WPO ou LTO. Évitez inline à moins que cela ne présente un avantage mesurable, ou si votre projet est si faible, la compilation n'est pas un problème, ou si votre temps est libre.