`* этот` наружный участник функция корпус?

В 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;
};