cplusplus / CWG

Core Working Group
23 stars 7 forks source link

CWG2869 [expr.prim.this] Restriction on where `this` can appear mishandles local classes #515

Open zygoloid opened 3 months ago

zygoloid commented 3 months ago

Reference (section label): [expr.prim.this]

Issue description: [expr.prim.this]/3 says, in part:

[this] shall not appear within the declaration of either a static member function or an explicit object member function of the current class (although its type and value category are defined within such member functions as they are within an implicit object member function).

... which disallows:

struct A {
  static void f() {
    struct B {
      void *g() { return this; }
    };
  }
};

... because this in g() appears within the declaration of A::f, which is a static member function.

Suggested resolution:

Change in [expr.prim.this]/3:

If a declaration declares a member function or member function template of a class X, the expression this is a prvalue of type “pointer to cv-qualifier-seq X” wherever X is the current class between the optional cv-qualifier-seq and the end of the function-definition, member-declarator, or declarator. It shall not appear within The declaration of either that determines the type of this shall declare neither a static member function or nor an explicit object member function of the current class (although its type and value category are defined within such member functions as they are within an implicit object member function).

(See also editorial issue https://github.com/cplusplus/draft/issues/6855.)

jensmaurer commented 3 months ago

CWG2869

t3nsor commented 3 months ago

I don't understand why this change is needed. The current wording says "... shall not appear within the declaration of either a static member function or an explicit object member function of the current class".

At the point where this appears, the current class is B, so the fact that we're inside a static member function of A is irrelevant as it should be: A is not the current class.

zygoloid commented 3 months ago

Hm. Maybe we just need clarification that the sentence is to be parsed as "shall not appear within the declaration of (either a static member function or an explicit object member function) of the current class" rather than as "shall not appear within the declaration of either (a static member function) or (an explicit object member function of the current class)"?

For example:

shall not appear within the declaration of either a static member function or an explicit object member function of the current class

... though it doesn't feel nice to split up the term "static member function" like that.

For what it's worth, I think the suggested change would still be an improvement, because it is correct by construction rather than by case analysis -- in particular, with the rule as written, we need to check whether (for example) we have problems with a friend declaration that redeclares a member of the current class in a nested scope. (I think that case is fine, but the point is that we need to be careful about such things, including when adding other features to the language in the future.)