Преобразование Lvalue в rvalue в [expr.ref]/2
Для первой опции (точка) первое выражение должно быть glvalue, имеющим полный тип класса. Для второй опции (стрелка) первое выражение должно быть значением, имеющим указатель на полный тип класса. Выражение E1->E2 преобразуется в эквивалентную форму (*(E1)).E2; остаток от [expr.ref] будет адресован только первой опции (точка).68 В любом случае, id-выражение должно называть члена класса или одного из его базовых классов. [Примечание: поскольку имя класса вставляется в его область видимости (пункт [класс]), имя класса также считается вложенным членом этого класса. - примечание конца] [Примечание: [basic.lookup.classref] описывает, как имена ищутся после. и -> операторы. - конец примечания]
Согласно этому параграфу преобразование lvalue в rvalue применяется к p
во фрагменте ниже. Но это не относится к a
, Почему стандарт предписывает glvalue для первого варианта (точка) и prvalue для второго варианта (стрелка)?
struct A{ void f() {} };
A a;
A* p = new A;
int main() {
a.f();
p->f();
}
1 ответ
Имейте в виду, что prvalues можно преобразовать в xvalues с помощью временного преобразования материализации [conv.rval]:
Prvalue типа
T
можно преобразовать в xvalue типаT
, Это преобразование инициализирует временный объект (15.2) типаT
из значения prvalue, оценивая значение prvalue с временным объектом в качестве объекта результата, и выдает значение xvalue, обозначающее временный объект.T
должен быть полным типом. [Примечание: еслиT
тип класса (или его массив), он должен иметь доступный и не удаляемый деструктор; см. 15.4. - примечание конца] [Пример:struct X { int n; }; int k = X().n; // OK, X() prvalue is converted to xvalue
- конец примера]
До введения этого нового преобразования prvalue-в-glvalue в C++14 не было ограничения для выражения postfix, являющегося glvalue.
На этой ноте C++11 был первой ревизией, в которой были представлены определяемые пользователем, неограниченные преобразования rvalue-to-lvalue с помощью (тогда-) нового ссылочного типа rvalue: auto&& x = f();
делает prvalue f()
в xvalue x
,