`* этот` наружный участник функция корпус?
В 5.1.1/3 стандарта С++ [expr.prim.general]
В отличие от выражения объекта в других контекстах *, это не обязательно для полного типа для целей доступа членов класса вне тела функции-члена. Только участники, объявленные ранее к декларации видны.
И вот этот пример:
struct A {
char g();
template<class T> auto f(T t) -> decltype(t + g())
{ return t + g(); }
};
template auto A::f(int t) -> decltype(t + g());
Можете ли вы объяснить цитату и пример? Что именно демонстрируется здесь?
Ответы
Ответ 1
Это означает, что вы можете получить доступ к элементам через this
, явно или неявно, внешние тела функции в определении класса. В этот момент тип является неполным, и обычно вы не можете получить доступ к элементам неполных типов.
Но вы можете делать это только в ограниченных частях объявления функции-члена; в предыдущем предложении говорится о this
:
Он не должен появляться перед необязательным cv-qualifier-seq
означает, что вы не можете использовать его в параметре или указании типа возвращаемого типа. Насколько я вижу, единственное место, где вы можете использовать его, вне тела функции, находится в концевом типе возврата.
Возможно, вам понадобится сделать это при использовании decltype
в концевом типе возвращаемого типа, чтобы получить тип выражения, включающего нестатический элемент. Этот пример демонстрирует это путем неявного использования this
для доступа к g()
в возвращаемом типе возврата. Было бы более ясно, что было продемонстрировано, если оно было написано как decltype(t + this->g())
.
Ответ 2
Что именно это пример? Какое утверждение здесь демонстрируется?
Показанное выражение:
В отличие от выражения объекта в других контекстах *, это не обязательно для полного типа для целей доступа членов класса (5.2.5) вне тела функции члена.
За пределами тела функции-члена имеется вызов g()
, что означает this->g()
. Там тип *this
(т.е. A
) не является полным.
В абзаце 9.2/2 стандарта С++ 11:
Класс считается полностью определенным типом объекта (3.9) (или полным типом) при закрытии }
спецификатора класса. В рамках класса-класса класс считается полным в функциональных телах, аргументы по умолчанию и скопированные или равные инициализаторы для нестатических членов данных (включая такие вещи в вложенные классы). В противном случае он считается неполным в пределах своей спецификации класса.
Ответ 3
Прежде всего, все выражения доступа членов преобразуются компилятором:
struct X{
int a;
void f(){}
void g(int b){
int x = a + b; // actually: int x = (*this).a + b
f(); // actually: (*this).f();
}
};
§9.3.1 [class.mfct.non-static] p3
[...] выражение id преобразуется в выражение доступа к члену класса (5.2.5), используя (*this)
(9.3.2) в качестве постфиксного выражения слева от оператора .
. [...]
Теперь пример из стандарта вызывает функцию-член за пределами тела другой функции-члена в типе trailing-return-type. И этот вызов также преобразуется:
template<class T> auto f(T t) -> decltype(t + (*this).g())
{ return t + (*this).g(); }
И вне тела функции-члена *this
, очевидно, является неполным типом. Это означает, что вы можете получить доступ только к именам, которые были объявлены до использования, но эта часть не относится только к использованию *this
:
struct X{
using typeA = int;
typeA f(); // OK, 'typeA' has been declared before
typeB g(); // Error: 'typeB' not declared before usage
using typeB = float;
};