Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Forward declaration of returned type of function

As this answer suggests, I know that it's allowed to use incomplete types as a return value in function's declaration. So I wrote the following code:

Obj.h

class Obj {
    int x;
};

f.h

class Obj;
Obj f();

f.cpp

#include "Obj.h"

Obj f() {
    return Obj();
}

main.cpp

#include "f.h"
int main() {
    f();
    return 0;
};

Compiling this code with the following compiler:

g++ (GCC) 4.8.5 20150623 (Red Hat 4.8.5-4)

using the following compilation command:

g++ *.cpp

gives the following error:

main.cpp: In function 'int main()':
main.cpp:4:7: error: invalid use of incomplete type 'class Obj'
     f();
       ^
f.h:1:7: error: forward declaration of 'class Obj'
 class Obj;
       ^

So the compiler is not allowing using incomplete type as a return value in a function's declaration. What's the explanation?

like image 791
Hanna Khalil Avatar asked Nov 10 '16 17:11

Hanna Khalil


Video Answer


1 Answers

As you stated it yourself "it's allowed to use incomplete types as a return value in function's declaration". That's exactly what the compiler allowed you to do. You successfully used an incomplete return type in non-defining function declaration - your declaration of f in f.h compiles without any problems.

But that's all you are allowed to do. And this does not in any way change the fact that:

  1. At the point of function definition the return type shall be complete
  2. At the point of function call the return type shall be complete.

In your code, inside main() you attempt to call a function declared with incomplete return type. Hence the error.

5.2.2 Function call [expr.call]

10 A function call is an lvalue if the result type is an lvalue reference type or an rvalue reference to function type, an xvalue if the result type is an rvalue reference to object type, and a prvalue otherwise.

11 If a function call is a prvalue of object type:

— if the function call is either — the operand of a decltype-specifier or — the right operand of a comma operator that is the operand of a decltype-specifier, a temporary object is not introduced for the prvalue. The type of the prvalue may be incomplete. [...]

— otherwise, the type of the prvalue shall be complete.

In other words, what you are allowed is to introduce an early forward declaration of your function with incomplete return type. But by the time you get to defining that function or calling it, you should have that return type completed.

like image 73
AnT Avatar answered Nov 15 '22 13:11

AnT