Обратите внимание, что практически во всех технических целях тип выражения никогда не считается ссылочным типом. [expr.type] / 1 :
Если выражение изначально имеет тип «ссылка на T
» ([dcl.ref], [dcl.init.ref]), тип настраивается на T
перед любым дальнейшим анализом.
Единственное заметное исключение - это когда decltype()
применяется к непереносимому имени или выражению доступа к члену класса.Хотя синтаксис рассматривает имя как выражение, семантический результат включает в себя объявленный тип имени вместо тип и категория значения выражения.
Итак, в вашем примере, x
lvalue типа int
, а rx
lvalue типа int
.После их объявлений и инициализаций язык вообще не делает различий между ними, за исключением повторного использования decltype(x)
или decltype(rx)
.
Это означает, что вычитание типа шаблона для Foo(rx)
работает точно так же, какдля Foo(x)
: тип A
равен int
, а не int&
, а аргумент является lvalue.По указанному вами правилу T
выводится как int&
, а при замене T=int&
на тип функции правило свертывания ссылок говорит, что T&&
равно int&
.