Используйте функцию, возвращающую неполный тип в качестве аргумента по умолчанию - PullRequest
0 голосов
/ 02 июля 2018

Когда я пытаюсь скомпилировать и запустить этот код (действительно только первые три строки имеют значение):

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(){}

Я получаю эту ошибку:

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;
       ^

Как мне заставить его скомпилироваться, не меняя порядок всего? В моем реальном коде объявления объединены, а определения распределены по нескольким файлам. Можно ли сделать решение без разделения объявлений?

Почему это важно, если на данном этапе тип является неполным?

Ответы [ 2 ]

0 голосов
/ 02 июля 2018

Как заставить его скомпилироваться, не меняя порядок всего?

Вам не нужно менять порядок всего , но вам нужно изменить порядок что-то . В частности, object должно быть определено до вызова getObject (в выражении аргумента по умолчанию).

Можно ли сделать решение без разделения объявлений?

Немного неясно, что это значит, но если вы определите object вверху, тогда объявления могут остаться точно такими же, как в вашем примере.

Другой вариант - повторно объявить функцию с аргументом по умолчанию после определения object:

class object;
object getObject();
void doSomething(object o);

class object{
    public:
        int num = 0;
};

void doSomething(object o = getObject());

Это, конечно, будет означать, что код после первого объявления, но до повторного объявления не получит преимущества от аргумента по умолчанию.

Наконец, немного хитрости. Выражения в шаблонах не должны быть полными, пока не будет создан экземпляр шаблона, поэтому ваш пример будет работать нормально, если бы doSomething был шаблоном функции:

template<class T=void>
void doSomething(object o = getObject());

class object{};

object getObject(){
    return {};
}

template<class T>
void doSomething(object o){}

Конечно, вы не должны создавать шаблон только для того, чтобы обойти эту проблему, но это удобная деталь, о которой нужно знать, когда вы пишете шаблоны.

0 голосов
/ 02 июля 2018

в момент ошибки объект был объявлен заранее, но его определение еще не достигло bean-компонента, поэтому объект имеет неполный тип. у вас могут быть указатели только на неполные типы.

вам нужно полное определение, подобное этому

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(){}

или если вы не хотите менять порядок, вы должны передать все по указателю

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(){}

но первое решение действительно лучше

...