Для первого параметра (точка) первое выражение должно быть 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();
}
Имейте в виду, что prvalues можно преобразовать в xvalues с помощью временного преобразования материализации [conv.rval]:
Prvalue типа
T
можно преобразовать в xvalue типаT
, Это преобразование инициализирует временный объект (15.2) типаT
из prvalue путем оценки prvalue с временным объектом в качестве его результата
объект, и создает значение x, обозначающее временный объект.T
должен быть полным типом. [Заметка: ЕслиT
тип класса (или его массив), он должен иметь доступный и не удаляемый деструктор; см. 15.4. — конечная нота] [пример:struct X { int n; }; int k = X().n; // OK, X() prvalue is converted to xvalue
— конец примера]
До введения этого нового преобразования prvalue-glvalue в C ++ 14 не было ограничений для постфикс-выражение быть ярким именем.
На этой ноте C ++ 11 был первой ревизией, в которой были представлены определяемые пользователем, неограниченные преобразования rvalue-to-lvalue с помощью (тогда-) нового ссылочного типа rvalue: auto&& x = f();
делает prvalue f()
в xvalue x
,
Других решений пока нет …