Incomplete types in member function definitions

2020-08-09 09:14发布

问题:

[dcl.fct.def] p2 states:

The type of a parameter or the return type for a function definition shall not be an incomplete or abstract (possibly cv-qualified) class type in the context of the function definition unless the function is deleted.

And [class.mem] p7 states:

A class is considered a completely-defined object type (or complete type) at the closing } of the class-specifier. The class is regarded as complete within its complete-class contexts; otherwise it is regarded as incomplete within its own class member-specification.

Given this code:

struct S
{
  // S is incomplete
  S f() {  /* S is complete in a function body */ return S(); }
  // S is incomplete 
};
// S is complete

A complete-class context notably does not include the decl-specifier-seq of the function definition, nor does it include the declarator of the function, however, every compiler says this is ok. What wording allows this, as I cannot find it?

回答1:

The very first item at the referred to link:

A complete-class context of a class is a

  • function body ([dcl.fct.def.general]),

So within the function body of any method is considered a complete-class context. The "context of a function definition" is synonymous with the function body, as far as I can tell -- as opposed to the context of a function declaration, where the return type is not required to be complete.



回答2:

I think that the compiler first finds tokens lex.phases 1.7 S class (with all of its members declared) and f member function (with just declaration, which includes the return type). Then, they are analyzed.

By the time the function body of f is analyzed the S class was analyzed first and considered as complete, because it has the member-function defined (the function boby is there, will be analyzed later).

Now S is complete, f can use return S().


But it his other case:

struct S {
    decltype(S{}) f() { return S(); }
};

the compiler wants to find the type of S by decltype so as to regard the token (the return type of f) and fails because the }; class-ending is not reached yet.