type et parenthèses

Je ne comprends pas la dernière ligne de l’exemple à la page 148 du FCD (§7.6.1.2 / 4):

const int&& foo(); int i; struct A { double x; }; const A* a = new A(); decltype(foo()) x1 = i; // type is const int&& decltype(i) x2; // type is int decltype(a->x) x3; // type is double decltype((a->x)) x4 = x3; // type is const double& 

Pourquoi les parenthèses font-elles une différence ici? Est-ce que ça ne devrait pas simplement être double comme dans la ligne ci-dessus?

Juste au-dessus de cet exemple, il est dit

  • Si e est une expression id sans parenthèse ou un access membre de classe (5.2.5), decltype (e) est le type de l’entité nommée par e.
  • si e est une lvalue, decltype (e) est T &, où T est le type de e;

Je pense que decltype(a->x) est un exemple de “l’access des membres de la classe” et decltype((a->x)) est un exemple de lvalue.

 decltype(a->x) 

Cela vous donne le type de la variable membre A::x , qui est double .

 decltype((a->x)) 

Cela vous donne le type de l’expression (a->x) , qui est une expression lvalue (d’où pourquoi il s’agit d’une référence const– a est un const A* ).

Les parens ajoutés en font une lvalue.

MSDN dit
Les parenthèses internes font que l’instruction soit évaluée en tant qu’expression au lieu d’un access membre. Et comme a est déclaré comme un pointeur const, le type est une référence à double const.