When I try to compile and run this code (only the first three lines really matter):
class object;
object getObject();
void doSomething(object o = getObject());
class object{
public:
int num = 0;
};
object getObject(){
return {};
}
void doSomething(object o){
o.num = 5;
}
int main(){}
I get this error:
main.cpp:3:39: error: invalid use of incomplete type 'class object'
void doSomething(object o = getObject());
^
main.cpp:1:7: note: forward declaration of 'class object'
class object;
^
How would I get it to compile without changing the order of everything? In my actual code, the declarations are together while the definitions are spread out across several files. Is it possible to do solve without separating the declarations?
Why does it matter if the type is incomplete at this stage?
How would I get it to compile without changing the order of everything?
You don't have to change the order of everything, but you do need to change the order of something. In particular, object
must be defined before getObject
is called (in the default argument expression).
Is it possible to do solve without separating the declarations?
It's a bit unclear what this means, but if you define object
at the top, then the declarations can remain exactly as they are in your example.
Another option is to re-declare the function with the default argument after object
definition:
class object;
object getObject();
void doSomething(object o);
class object{
public:
int num = 0;
};
void doSomething(object o = getObject());
This of course would mean that the code after the first declaration, but before re-declaration won't benefit from the default argument.
Lastly, a bit of a trick. Expressions within templates don't need to be complete until the template is instantiated, so your example would work fine if doSomething
was a function template:
template<class T=void>
void doSomething(object o = getObject());
class object{};
object getObject(){
return {};
}
template<class T>
void doSomething(object o){}
Of course, you shouldn't make a template just to get around this issue, but this is a handy detail to be aware of when you do write templates.
at the point of the error, object has been forward declared but his definition has not bean reached yet so object is an incomplete type. you can only have pointers on incomplete types.
you need to have a full definition like this
class object{
public:
int num = 0;
};
object getObject();
void doSomething(object o = getObject());
object getObject(){
return {};
}
void doSomething(object o){
o.num = 5;
}
int main(){}
or if you don't want to reorder you have to pass every thing by pointer
class object;
object* getObject();
void doSomething(object* o = getObject());
class object{
public:
int num = 0;
};
object* getObject(){
return new object();
}
void doSomething(object* o){
o->num = 5;
delete o;
}
int main(){}
but the first solution is really better
来源:https://stackoverflow.com/questions/51139207/use-function-returning-incomplete-type-as-default-argument