Decltype и круглые скобки

Я не понимаю последнюю строку примера на стр. 148 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&

Почему круглые скобки имеют значение здесь? Разве это не должно быть double как в строке выше?

Ответ 1

Как раз над этим примером, он говорит

  • если e - это несферированное идентификационное выражение или доступ к члену класса (5.2.5), decltype (e) - это тип объекта, названного e.
  • если e является lvalue, decltype (e) является T &, где T - тип e;

Я думаю, что decltype(a->x) является примером "доступа к члену класса" и decltype((a->x)) является примером lvalue.

Ответ 2

decltype(a->x)

Это дает вам тип переменной-члена A::x, которая double.

decltype((a->x))

Это дает вам тип выражения (a->x), который является выражением lvalue (следовательно, почему он является ссылкой на константу - a является const A*).

Ответ 3

Добавленные parens превращают его в lvalue.

MSDN говорит
Внутренние скобки заставляют оператор вычисляться как выражение вместо доступа к члену. И поскольку a объявлен как указатель const, тип является ссылкой на const double.