Строго по стандарту, похоже, вы правы, и должно быть double &&
.Моя цепочка рассуждений (все цитаты из C ++ 17 (n4659)):
8.2.5 Доступ к членам класса [expr.ref]
1 Постфиксное выражение, за которым следуетточка .
или стрелка ->
, за которыми необязательно следует ключевое слово template
(17.2), а за которым следует id-выражение , является постфиксным выражением....
2 Для первого параметра (точка) первое выражение должно быть glvalue, имеющим полный тип класса.
3 Сокращение postfix-expression.id-expression поскольку E1.E2
, E1
называется выражением объекта .... Тип и категория значения E1.E2
определяются следующим образом.В оставшейся части 8.2.5 cq представляет либо const
, либо отсутствие const
, а vq представляет либо volatile
, либо отсутствие volatile
. cv представляет произвольный набор cv-квалификаторов, как определено в 6.9.3.
...
(4.2) Если E2
не является статичнымэлемент данных и тип E1
равен « cq1 vq1 X
», а тип E2
равен « cq2 vq2 T
», выражение обозначаетименованный член объекта, обозначенного первым выражением.Если E1
является lvalue, то E1.E2
является lvalue;в противном случае E1.E2
является значением xvalue....
Таким образом, если левый операнд .
является значением x, то и результат всего выражения .
.
8.2.3 Явныйпреобразование типов (функциональная запись) [expr.type.conv]
1 A спецификатор простого типа (10.1.7.2) или спецификатор типа (17.6), за которым следует необязательный список выражений в скобках или braced-init-list (инициализатор), создающий значение указанного типа с учетом инициализатора....
2 ... выражение является prvalue указанного типа, чей объект-результат инициализируется напрямую (11.6) с помощью инициализатора.
То есть A()
isprvalue.
Наконец:
8 выражений [expr]
10 Всякий раз, когда выражение prvalue появляется как операнд оператора, который ожидает glvalue для этого операндапреобразование временной материализации (7.4) применяется для преобразования выражения в значение x.
В совокупности это означает, что A()
является prvalue (из 8.2.3 / 2).Поскольку .
требует, чтобы его операнд LHS был glvalue, применяется временное преобразование материализации (на 8/10), а результатом является xvalue.Итак, начиная с 8.2.5 / (4.2), поскольку E1
является значением x, равно E1.E2
, что в вашем случае составляет A().x
.
Что касается decltype
:
10.1.7.2 Спецификаторы простых типов [dcl.type.simple]
4 Для выражения e
тип, обозначаемый decltype(e)
, определяется следующим образом:
...
(4.3) ... если e
является значением x, decltype(e)
является T&&
, где T
является типом e
;
Поскольку в вашем случае (A().x)
было определено как xvalue, его dectlype
должно быть double &&
.