Considérez cet exemple de cppreference :
struct S { static const int x = 1; };
void f() { &S::x; } // discarded-value expression does not odr-use S::x
Je suis d'accord que &S::x
est une expression de valeur supprimée, puisque la norme dit (9.2, paragraphe 1 [stmt.expr] de n47 )
Les énoncés d'expression ont la forme
expression-statement: expression_opt ;
L'expression est une expression à valeur rejetée (article 8) ...
Cependant, est-ce suffisant pour S::x
ne pas être odr-used? 6.2, paragraphe 3 [basic.def.odr] stipule
Une variable
x
dont le nom apparaît comme une expression potentiellement évaluéeex
est odr-used parex
sauf si
- ...
- si
x
est un objet,ex
est un élément de l'ensemble des résultats potentiels d'une expressione
, où soit
- la conversion lvalue-to-rvalue (7.1) est appliquée à
e
, oue
est une expression à valeur rejetée (article 8) .
Le problème est que l'expression de valeur supprimée &S::x
n'a aucun résultat potentiel (ce qui signifie que S::x
n'est pas le résultat potentiel de &S::x
), comme vous pouvez le voir dans 6.2, paragraphe 2 [basic.def.odr]:
... L'ensemble des résultats potentiels d'une expression
e
est défini comme suit:
- Si
e
est une expression id (8.1.4), l'ensemble contient uniquemente
.- Si
e
est une opération d'indexation (8.2.1) avec un opérande de tableau, l'ensemble contient les résultats potentiels de cet opérande.- ...
- Sinon, l'ensemble est vide.
Ensuite, comment pouvez-vous expliquer que S::x
n'est pas utilisé?
Il est en effet un peu utilisé. Votre analyse est correcte (et j'ai corrigé cet exemple il y a quelque temps ).
Oui, dans l'exemple, &S::x
odr utilise S::x
.
[basic.def.odr]/4
Une variable
x
dont le nom apparaît comme une expression potentiellement évaluéeex
est odr-used parex
à moins d'appliquer la valeur-à-l La conversion de rvalue enx
donne une expression constante qui n'invoque aucune fonction non triviale et, si x est un objet, ex est un élément de l'ensemble des résultats potentiels d'une expression e, où soit la conversion de lvalue en rvalue est appliquée à e, soit e est une expression de valeur rejetée.
L'adresse d'un objet n'est jamais une expression constante. C'est pourquoi S::x
est utilisé dans &S::x
.
Pour justifier cette dernière affirmation:
[expr.const]/6
Une expression constante est soit une expression constante de noyau glvalue qui fait référence à une entité qui est le résultat autorisé d'une expression constante (telle que définie ci-dessous), soit une expression constante de noyau prvalue dont la valeur satisfait les contraintes suivantes [...]
et
[expr.const]/2.7
2) Une expression
e
est une expression constante de base sauf si l'évaluation dee
, suit les règles de l'abstrait machine , évaluerait l'une des expressions suivantes:
[...]
2.7) une conversion de lvalue en rvalue à moins qu'elle ne soit appliquée à
(aucun des points suivants ne s'applique :)
2.7.1) une valeur gl non volatile de type intégral ou énumération qui fait référence à un objet const complet non volatil avec une initialisation précédente, initialisé avec une expression constante, ou
2.7.2) une valeur gl non volatile qui fait référence à un sous-objet d'un littéral de chaîne, ou
2.7.3) une valeur gl non volatile qui fait référence à un objet non volatil défini avec constexpr, ou qui fait référence à un sous-objet non mutable d'un tel objet, ou
2.7.4) une valeur gl non volatile de type littéral qui se réfère à un objet non volatile dont la durée de vie a commencé dans le cadre de l'évaluation dee
;