How am I able to use an incomplete class as an argument in itself?

struct test{
 void call(test t1){
   //
 }
};

I have asked a similar question and found a few other links such as:

How am I able to use a class as a function parameter in itself?

Incomplete types in member function definitions

But none of them answer this question:

The compiler needs to emit code to allocated space on the stack for t1, but at that point test is incomplete so how would it know how much space it needs?


The class struct test is not an incomplete type.

From cppreference.com:

Incomplete type

  • the type void (possibly cv-qualified);
  • incompletely-defined object types
    • class type that has been declared (e.g. by forward declaration) but not defined;
    • array of unknown bound;
    • array of elements of incomplete type;
    • enumeration type from the point of declaration until its underlying type is determined.

All other types are complete.

Test it out yourself, put a test into your call function, like:

void call(test t1)
{
    std::cout << sizeof t1 << std::endl;
}

The answer is in the answers of your linked question (Incomplete types in member function definitions): the struct is complete in the context of the function definition.

Hence the C++ compiler will need to read the entire definition of struct test before generating the code of the call() function, but that is a compiler implementation issue.

It is also allowed to refer to member variables which are defined later in the struct definition:

struct test{
 void call(test t1){
   a += t1.a;
 }
 int a;
};

Compiling a class definition is not a single-pass process.

Member functions are compiled only after it has been determined what the members are, just like if the function definitions were located "outside".

In other words, the compiler doesn't emit any code for the function until the class definition is complete.