Сначала несколько предварительных абзацев:
[основной]
3 Сущность - это значение, объект, ссылка, функция, перечислитель,
тип, член класса, шаблон, специализация шаблона, пространство имен,
пакет параметров, или это.
[dcl.type.simple]
4 Тип, обозначаемый decltype(e)
, определяется следующим образом:
, если e
- не заключенное в скобки id-выражение или доступ к члену класса без скобок ([expr.ref]), decltype(e)
- это тип
сущность с именем e
. Если такой сущности нет, или если e называет набор
из-за перегруженных функций программа некорректна;
в противном случае, если e
является значением x, decltype(e)
является T&&
, где T
является типом e
;
В противном случае, если e - lvalue, decltype(e)
- T&
, где T
- тип e
;
в противном случае decltype(e)
является типом e
.
[dcl.ref]
1 В объявлении T D
, где D
имеет одну из форм
& <i>attribute-specifier-seq</i><sub>opt</sub> D1
&& <i>attribute-specifier-seq</i><sub>opt</sub> D1
и тип идентификатора в объявлении T D1
« производный-декларатор-тип-список T
», затем тип идентификатора
D
- это « список производных-объявлений-типов ссылка на T
.»
[выражение]
5 Если выражение изначально имеет тип «ссылка на T
»
([dcl.ref], [dcl.init.ref]), тип настраивается на T
до любого
дальнейший анализ. Выражение обозначает объект или функцию
обозначается ссылкой, а выражение является lvalue или
xvalue, в зависимости от выражения.
[expr.prim.general]
8 Идентификатор является id-выражением при условии, что он был соответствующим образом
объявлено (пункт [dcl.dcl]). Тип выражения является типом
идентификатор. Результатом является объект, обозначенный идентификатором.
Результатом является lvalue, если сущность является функцией, переменной или данными
член и prvalue в противном случае.
[expr.call]
10 Вызов функции является lvalue, если тип результата является lvalue
ссылочный тип или rvalue ссылка на тип функции, xvalue, если
тип результата - это rvalue-ссылка на тип объекта и prvalue
в противном случае.
Что теперь позволяет нам отвечать на ваши вопросы.
В строке 1 x
является идентификатором (id-выражением), который называет параметр функции. Его тип int&&
, и этот тип возвращает decltype(x)
. x
не является выражением и не имеет категории значения.
Да, в некотором роде. x
в декларации не является выражением. Но в качестве аргумента decltype
является выражением. Однако он попадает в особый случай первого маркера decltype
, поэтому выводится тип идентификатора с именем x
вместо типа x
в качестве выражения.
В строке 2 x
является выражением. До корректировки типа его тип равен int&&
, а после типа становится int
. Категория значения lvalue.
Да.
В строке 3 std::move(x)
является выражением. Тип до регулировки int&&
, после - int
. Категория значения - xvalue.
Да.
Когда мы говорим, что x
имеет ссылочный тип rvalue, мы ссылаемся либо на тип x
в качестве идентификатора, либо на тип x
в качестве выражения перед настройкой типа.
Да.
Слово «тип» в выражении «Каждое выражение имеет некоторый нереферентный тип, и каждое выражение принадлежит ровно к одной из трех основных категорий значений» на cppreference.com относится к типу после корректировки типа.
Да.
КогдаСкотт Мейерс пишет: «Если тип выражения является ссылкой на lvalue (например, T&
или const T&
и т. Д.), Это выражение является lvalue».он ссылается на тип до корректировки, а второе слово «lvalue» относится к категории значений.
Не могу точно сказать, что имел в виду Скотт Мейерс, когда писал это, но этода, только толкование слов, соответствующее стандарту, да.