c ++ quadtree является неполным типом - PullRequest
0 голосов
/ 05 апреля 2020

Я реализую quadtree в библиотеке, и компилятор продолжает выдавать ошибки, говоря о неполном типе: quadtree.h

template<int capacity,
         typename t,
         typename = std::enable_if<std::is_base_of<hasDim, t>::value && std::is_pointer<t>::value>>
struct quadtree {
    bool divided = false;
    quadtree<capacity, t>* nw,* ne,* sw,* se;
    std::vector<t> objs;
    rect2 b;

    quadtree(rect2 bounds): b(b) {}

    void addObj(t);
    void divide();
    void assign(t);
    void empty();
};

bin. cpp

#include "quadtree.h"

template<int capacity,
         typename t,
         typename = std::enable_if<std::is_base_of<hasDim, t>::value && std::is_pointer<t>::value>>
void quadtree<capacity, t>::addObj(t o) {
    if(!divided) {
        objs.push_back(o);
        if(objs.size() > capacity) {
            divide();
        }
    } else {
        assign(o);
    }
}

template<int capacity,
         typename t,
         typename = std::enable_if<std::is_base_of<hasDim, t>::value && std::is_pointer<t>::value>>
void quadtree<capacity, t>::divide() {
    divided = true;
    nw = new quadtree<capacity, t>(rect2(b.x(), b.y(), b.w()/2, b.h()/2));
    ne = new quadtree<capacity, t>(rect2(b.x()+b.w()/2, b.y(), b.w()/2, b.h()/2));
    sw = new quadtree<capacity, t>(rect2(b.x(), b.y()+b.h()/2, b.w()/2, b.h()/2));
    se = new quadtree<capacity, t>(rect2(b.x()+b.w(), b.y()+b.h(), b.w()/2, b.h()/2));
    for(auto o: objs) {
        assign(o);
    }
    objs.resize(0);
}

template<int capacity,
         typename t,
         typename = std::enable_if<std::is_base_of<hasDim, t>::value && std::is_pointer<t>::value>>
void quadtree<capacity, t>::assign(t o) {
    rect2 orect = o.makeRect();
    if(orect.intersects(nw.bounds)) {nw.addObj(o);}
    if(orect.intersects(ne.bounds)) {ne.addObj(o);}
    if(orect.intersects(sw.bounds)) {sw.addObj(o);}
    if(orect.intersects(se.bounds)) {se.addObj(o);}
}

template<int capacity,
         typename t,
         typename = std::enable_if<std::is_base_of<hasDim, t>::value && std::is_pointer<t>::value>>
void quadtree<capacity, t>::empty() {
    if(divided) {
        divided = false;
        nw.empty(); ne.empty(); sw.empty(); se.empty();
        delete nw, ne, sw, se;
    } else {
        objs.resize(0);
    }
}

Согласно microsoft , неполный тип - это тот, размер которого не может быть определен, но здесь я понятия не имею, откуда это может быть получено: bool divided можно определить; quadtree<capacity, t>* s - это указатели, размер которых можно определить; std::vector<t> objs - это вектор, что означает, что он хранит динамически распределенный массив, что означает, что его размер также может быть определен; То же самое касается rect2 b, который хранит только 4 двойных. Любая идея, откуда может возникнуть проблема?

РЕДАКТИРОВАТЬ:

Вот сообщение об ошибке:

bin.cpp:32:40: error: invalid use of incomplete type 'struct quadtree<capacity, t>'
   32 |  void quadtree<capacity, t>::addObj(t o) {
      |

Ответы [ 3 ]

1 голос
/ 05 апреля 2020

Согласно Microsoft, неполный тип - это тот, размер которого не может быть определен

Это не то, что означает «неполный тип». Это свойство применяется к неполным типам.

Неполный тип - это тип, который не был определен. Пример:

class X;            // this is not a definition; X is incomplete
auto s = sizeof(X); // program is ill-formed because size of X is not known

Определение функций-членов класса - это еще одна вещь, которую нельзя сделать для неполного типа. Пример:

class Y;            // this is not a definition; Y is incomplete
Y::Y() {}           // program is ill-formed because Y is incomplete

Возвращаясь к вашей проблеме: Вы пытаетесь определить функции-члены quadtree в пределах bin. cpp, даже если bin. cpp не содержит определения quadtree. quadtree должен быть определен первым. Просто включите заголовок, который содержит определение.

0 голосов
/ 05 апреля 2020

Проблема в том, как вы определяете функции-члены, принадлежащие классу шаблона.

В своем объявлении класса вы говорите, что quadtree - это шаблон, который принимает 3 параметра, но когда вы go для определения функций-членов вы перечисляете только два.

Чтобы исправить это, вам нужно просто указать, что шаблон принимает эти три параметра:

template<int capacity,
         typename t,
         typename z>
void quadtree<capacity, t, z>::divide() {

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

В качестве альтернативы вы можете просто определить встроенные функции в определении класса шаблона.

И имейте в виду, что определения классов шаблонов должны go в заголовочном файле , а не в *. 1018 * файле.

0 голосов
/ 05 апреля 2020

В quadtree.h вы определяете структуру, но внутри структуры, которую вы уже используете в встроенном определении конструктора (quadtree(rect2 bounds): b(b) {}), это недопустимо, поскольку она еще не полностью определена. Компилятор не может сгенерировать код конструктора, потому что он еще не знает, сколько еще элементов данных может прийти.

Вы можете избежать этой проблемы, только объявив конструктор: quadtree(rect2 bounds): b(b);, а затем отдельно (после } структуры), добавив определение template<...> quadtree::quadtree(rect2 bounds) {}

...