Reputation: 1171
I've encountered an error in my a templated class I've made that holds a pointer to children it later creates. The error generated is a bit weird as I've never seen it.
Code:
template <size_t maxObjects, size_t maxDepth, bool canDelete = false, size_t depth = 0>
struct DynamicQT
{
public:
DynamicQT(const Aabb2& aabb) : aabb(aabb)
{
}
~DynamicQT()
{
clearObjects();
destroyBranches();
}
void insert(Object* object)
{
if (hasBranches())
{
if (object->getAABB().overlaps(tl->aabb)) tl->insert(object);
if (object->getAABB().overlaps(tr->aabb)) tr->insert(object);
if (object->getAABB().overlaps(bl->aabb)) bl->insert(object);
if (object->getAABB().overlaps(br->aabb)) br->insert(object);
}
else objects[(size_t)object] = object;
}
void remove(Object* object)
{
if (hasBranches())
{
if (object->getAABB().overlaps(tl->aabb)) tl->remove(object);
if (object->getAABB().overlaps(tr->aabb)) tr->remove(object);
if (object->getAABB().overlaps(bl->aabb)) bl->remove(object);
if (object->getAABB().overlaps(br->aabb)) br->remove(object);
}
else
{
auto result = objects.find((size_t)object);
if (result != objects.end())
objects.erase((size_t)object);
}
}
void query(const Aabb2& queryRect, std::vector<Object*>& outVec)
{
std::map<size_t, Object*> outMap;
query(queryRect, outMap);
if (depth == 0)
{
for (const auto& item : objects)
outVec.push_back(item.second);
}
}
void update()
{
throw;
}
public:
void query(const Aabb2& queryRect, std::map<size_t, Object*>& outMap)
{
if (hasBranches())
{
if (queryRect.overlaps(tl->aabb)) tl->query(queryRect, outMap);
if (queryRect.overlaps(tr->aabb)) tr->query(queryRect, outMap);
if (queryRect.overlaps(bl->aabb)) bl->query(queryRect, outMap);
if (queryRect.overlaps(br->aabb)) br->query(queryRect, outMap);
}
else outMap.insert(objects.begin(), objects.end());
}
void clearObjects()
{
if (canDelete)
{
for (const auto& obj : objects)
if (obj.second) delete obj.second;
}
objects.clear();
}
void createBranches()
{
if (!hasBranches() && depth < maxDepth)
{
Vector2 half = aabb.halfWidths();
Aabb2 a(aabb.pos, half);
Aabb2 b(aabb.pos.addX(half.x), half);
Aabb2 c(aabb.pos.addY(half.y), half);
Aabb2 d(aabb.center(), half);
tl = new DynamicQT<maxObjects, maxDepth, canDelete, depth + 1>(a);
tr = new DynamicQT<maxObjects, maxDepth, canDelete, depth + 1>(b);
bl = new DynamicQT<maxObjects, maxDepth, canDelete, depth + 1>(c);
br = new DynamicQT<maxObjects, maxDepth, canDelete, depth + 1>(d);
}
}
void passObjectsToBranches()
{
if (hasBranches())
{
Object* obj = nullptr;
for (const auto& item : objects)
{
obj = item.second;
if (obj->getAABB().overlaps(tl->aabb)) tl->insert(obj);
if (obj->getAABB().overlaps(tr->aabb)) tr->insert(obj);
if (obj->getAABB().overlaps(bl->aabb)) bl->insert(obj);
if (obj->getAABB().overlaps(br->aabb)) br->insert(obj);
}
clearObjects();
}
}
void getObjectsFromBranches()
{
if (hasBranches())
{
objects.insert(tl->objects.begin(), tl->objects.end());
objects.insert(tr->objects.begin(), tr->objects.end());
objects.insert(bl->objects.begin(), bl->objects.end());
objects.insert(br->objects.begin(), br->objects.end());
}
}
void destroyBranches()
{
if (hasBranches())
{
delete tl;
delete tr;
delete bl;
delete br;
}
}
bool hasBranches() const
{
return (tl && tr && bl && br);
}
public:
private:
Aabb2 aabb;
DynamicQT* tl = nullptr;
DynamicQT* tr = nullptr;
DynamicQT* bl = nullptr;
DynamicQT* br = nullptr;
std::map<size_t, Object*> objects;
};
Note: update is yet to be implemented
The exact error is:
error C2440: '=' : cannot convert from 'DynamicQT<10,10,true,1> *' to 'DynamicQT<10,10,true,0> *'
When I searched for the fix, I had to remove the "depth + 1" or just remove the "+ 1" and compiles fine but obviously is not supposed to happen.
Any help is appreciated (And maybe any problems with the code).
Upvotes: 1
Views: 60
Reputation: 119641
The template parameters of DynamicQT
are part of the type of the instantiation. Therefore, DynamicQT<10,10,true,0>
and DynamicQT<10,10,true,1>
are unrelated types and their pointers cannot be implicitly converted to each other. It seems that if depth
is 0 then the children should have depth 1 and so on, so you should declare the child pointers to have the appropriate type:
private:
Aabb2 aabb;
typedef DynamicQT<maxObjects, maxDepth, canDelete, depth+1> ChildDynamicQT;
ChildDynamicQT* tl = nullptr;
ChildDynamicQT* tr = nullptr;
ChildDynamicQT* bl = nullptr;
ChildDynamicQT* br = nullptr;
Upvotes: 1