Les parenthèses en C ++ sont utilisées à de nombreux endroits: par exemple dans les appels de fonction et les expressions de regroupement pour remplacer la priorité des opérateurs. En dehors des parenthèses supplémentaires illégales (comme autour des listes d'arguments d'appel de fonction), une règle générale - mais pas absolue - de C ++ est que les parenthèses supplémentaires ne font jamais de mal :
5.1 Expressions primaires [expr.prim]
5.1.1 Général [expr.prim.general]
6 Une expression entre parenthèses est une expression principale dont le type et la valeur sont identiques à ceux de l'expression incluse. La présence de parenthèses n'affecte pas si l'expression est une lvalue. L'expression entre parenthèses peut être utilisée exactement dans les mêmes contextes que ceux où l'expression incluse peut être utilisée, et avec la même signification, sauf indication contraire .
Question : dans quels contextes les parenthèses supplémentaires changent-elles la signification d'un programme C ++, autre que la priorité de l'opérateur de base?
REMARQUE : Je considère que la restriction de la syntaxe pointeur vers membre&qualified-id
sans parenthèses est en dehors de la portée, car elle restreint la syntaxe plutôt que d'autoriser deux syntaxes avec des significations différentes. De même, l'utilisation de parenthèses dans les définitions de macros de préprocesseur protège également contre la préséance indésirable des opérateurs.
la source
&(C::f)
, l'opérande de&
est toujoursC::f
, n'est-ce pas?expr.unary.op/4
: Un pointeur vers un membre n'est formé que lorsqu'un explicite&
est utilisé et que son opérande est un identifiant qualifié non placé entre parenthèses.()
sur le sélecteur de pointeur vers membre::*
Réponses:
TL; DR
Les parenthèses supplémentaires changent la signification d'un programme C ++ dans les contextes suivants:
decltype
expressionsEmpêcher la recherche de noms dépendants des arguments
Comme il est détaillé dans l'annexe A de la norme, a
post-fix expression
du formulaire(expression)
est unprimary expression
, mais pas unid-expression
, et donc pas ununqualified-id
. Cela signifie que la recherche de nom dépendante de l'argument est empêchée dans les appels de fonction de la forme(fun)(arg)
par rapport à la forme conventionnellefun(arg)
.3.4.2 Recherche de nom dépendante de l'argument [basic.lookup.argdep]
Activation de l'opérateur virgule dans les contextes de liste
L'opérateur virgule a une signification particulière dans la plupart des contextes de type liste (arguments de fonction et de modèle, listes d'initialiseurs, etc.). Les parenthèses du formulaire
a, (b, c), d
dans de tels contextes peuvent activer l'opérateur virgule par rapport au formulaire normala, b, c, d
où l'opérateur virgule ne s'applique pas.5.18 Opérateur virgule [expr.comma]
Résolution de l'ambiguïté des analyses vexantes
La rétrocompatibilité avec C et sa syntaxe de déclaration de fonction arcane peut conduire à des ambiguïtés d'analyse surprenantes, appelées analyses vexantes. Essentiellement, tout ce qui peut être analysé en tant que déclaration sera analysé comme une seule , même si une analyse concurrente s'appliquerait également.
6.8 Résolution d'ambiguïté [stmt.ambig]
8.2 Résolution des ambiguïtés [dcl.ambig.res]
Un exemple célèbre de ceci est le Most Vexing Parse , un nom popularisé par Scott Meyers dans le point 6 de son livre Effective STL :
Cela déclare une fonction
data
, dont le type de retour estlist<int>
. Les données de fonction prennent deux paramètres:dataFile
. C'est le typeistream_iterator<int>
. Les parenthèses autourdataFile
sont superflues et ignorées.istream_iterator<int>
.Placer des parenthèses supplémentaires autour du premier argument de fonction (les parenthèses autour du deuxième argument sont illégales) résoudra l'ambiguïté
C ++ 11 a une syntaxe d'initialisation d'accolades qui permet de contourner ces problèmes d'analyse dans de nombreux contextes.
Déduire le référencé dans les
decltype
expressionsContrairement à la
auto
déduction de type,decltype
permet de déduire la référence (références lvalue et rvalue). Les règles distinguent les expressionsdecltype(e)
etdecltype((e))
:7.1.6.2 Spécificateurs de type simple [dcl.type.simple]
Les règles pour
decltype(auto)
ont une signification similaire pour les parenthèses supplémentaires dans le RHS de l'expression d'initialisation. Voici un exemple de la FAQ C ++ et de ces questions et réponses connexesLe premier retourne
string
, le second retournestring &
, qui est une référence à la variable localestr
.Prévention des erreurs liées aux macros de préprocesseur
Il existe une foule de subtilités avec les macros de préprocesseur dans leur interaction avec le langage C ++ proprement dit, dont les plus courantes sont répertoriées ci-dessous
#define TIMES(A, B) (A) * (B);
afin d'éviter la préséance indésirable des opérateurs (par exemple, dansTIMES(1 + 2, 2 + 1)
lequel donne 9 mais donnerait 6 sans les parenthèses autour(A)
et(B)
assert((std::is_same<int, int>::value));
qui autrement ne compileraient pas(min)(a, b)
(avec l'effet secondaire indésirable de désactiver également ADL)la source
if
/while
si l'expression est une affectation. Par exempleif (a = b)
- avertissement (vouliez-vous dire==
?), Tandis queif ((a = b))
- aucun avertissement.(min)(a, b)
(avec une mauvaise MACROmin(A, B)
) fait partie de la prévention de la recherche de nom dépendante des arguments?En général, dans les langages de programmation, les parenthèses "supplémentaires" impliquent qu'elles ne changent pas l'ordre d'analyse syntaxique ou la signification. Ils sont ajoutés pour clarifier l'ordre (priorité des opérateurs) au profit des personnes lisant le code, et leur seul effet serait de ralentir légèrement le processus de compilation et de réduire les erreurs humaines dans la compréhension du code (accélérant probablement le processus de développement global ).
Si un ensemble de parenthèses modifie réellement la façon dont une expression est analysée, elles ne sont par définition pas extra. Les parenthèses qui transforment une analyse illégale / invalide en une analyse légale ne sont pas "extra", bien que cela puisse indiquer une mauvaise conception du langage.
la source