Use function returning incomplete type as default argument

空扰寡人 提交于 2019-12-07 13:17:16

问题


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?


回答1:


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.




回答2:


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!