Andrew Tomazos
Andrew Tomazos

Reputation: 68618

`*this` outside member function body?

In 5.1.1/3 of C++ standard [expr.prim.general]

Unlike the object expression in other contexts, *this is not required to be of complete type for purposes of class member access outside the member function body. Only class members declared prior to the declaration are visible.

And then this example:

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());

Can you explain the quote and the example? What exactly is being demonstrated here?

Upvotes: 10

Views: 498

Answers (3)

Mike Seymour
Mike Seymour

Reputation: 254431

It means that you can access members via this, either explicitly or implicitly, outside function bodies within a class definition. At that point, the type is incomplete, and usually you can't access members of incomplete types.

But you can only do that within restricted parts of a member function declaration; the previous sentence says about this:

It shall not appear before the optional cv-qualifier-seq

meaning that you can't use it in a parameter or leading return type specification. As far as I can see, the only place you can use it, outside a function body, is in a trailing return type.

You might need to do this when using decltype in a trailing return type, to get the type of an expression involving a non-static member. The example demonstrates this by implicitly using this to access g() in the trailing return type. It would have been more clear what was being demonstrated if it were written as decltype(t + this->g()).

Upvotes: 4

Xeo
Xeo

Reputation: 131789

First of all, all member access expressions are transformed by the compiler:

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

[...] the id-expression is transformed into a class member access expression (5.2.5) using (*this) (9.3.2) as the postfix-expression to the left of the . operator. [...]

Now, the example from the standard calls a member function outside of the body of another member function, in the trailing-return-type. And that call is transformed too:

template<class T> auto f(T t) -> decltype(t + (*this).g()) 
{ return t + (*this).g(); }

And outside of a member function body, *this is obviously an incomplete type. This means that you can only access the names that have been declared prior to the usage - but that part does not apply only to the *this usage:

struct X{
  using typeA = int;
  typeA f(); // OK, 'typeA' has been declared before

  typeB g(); // Error: 'typeB' not declared before usage
  using typeB = float;
};

Upvotes: 2

Andy Prowl
Andy Prowl

Reputation: 126432

What exactly is this an example of? Which statement is being demonstrated here?

The statement being demonstrated is that:

Unlike the object expression in other contexts, *this is not required to be of complete type for purposes of class member access (5.2.5) outside the member function body.

Outside the body of the member function there is an invocation to g(), which means this->g(). There, the type of *this (i.e. A) is not complete.

Per paragraph 9.2/2 of the C++11 Standard:

A class is considered a completely-defined object type (3.9) (or complete type) at the closing } of the class-specifier. Within the class member-specification, the class is regarded as complete within function bodies, default arguments, and brace-or-equal-initializers for non-static data members (including such things in nested classes). Otherwise it is regarded as incomplete within its own class member-specification.

Upvotes: 6

Related Questions