c ++四叉树的问题
Problems with c++ 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>*
是指针,其大小可以确定; 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) {
|
According to microsoft, an incomplete type is one whose size can't be determined
那不是 "incomplete type" 的意思。这是适用于不完整类型的 属性。
不完整类型是指尚未定义的类型。示例:
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 的成员函数是另一件不能为不完整类型完成的事情。示例:
class Y; // this is not a definition; Y is incomplete
Y::Y() {} // program is ill-formed because Y is incomplete
回到您的问题:您试图在 bin.cpp 中定义 quadtree
的成员函数,即使 bin.cpp 不包含 quadtree
的定义。 quadtree
必须先定义。只需包含包含定义的 header。
在quadtree.h
中定义结构,但在结构内部您已经在构造函数的内联定义中使用它(quadtree(rect2 bounds): b(b) {}
),这是不允许的,因为它不是尚未完全定义。编译器无法生成构造函数的代码,因为它还不知道还会有多少数据成员。
您可以通过仅声明构造函数来避免此问题:quadtree(rect2 bounds): b(b);
,然后单独(在[=结构的 13=] 添加其定义 template<...> quadtree::quadtree(rect2 bounds) {}
问题在于如何定义属于模板的成员函数 class。
在你的class声明中,你说quadtree
是一个有3个参数的模板,但是当你去定义成员函数时,你只列出了两个。
要修复它,您只需指定模板采用这三个参数:
template<int capacity,
typename t,
typename z>
void quadtree<capacity, t, z>::divide() {
您没有在这里指定第三个参数的默认值,因为您在声明模板时已经这样做了。
作为替代方案,您可以在模板 class 定义中定义内联函数。
请记住,模板 class 定义需要 in the header file,而不是 .cpp 文件。
来自(相当长的)未来的我,解决方案是放弃 std::enable_if
s。我仍然不清楚为什么它们会导致问题,但是在 class 正文中用一个 static_assert
替换它们就足以解决问题。无论如何,孩子们,不要使用这个代码。太可怕了。
我正在一个库中实现一个四叉树,编译器不断抛出关于不完整类型的错误: 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>*
是指针,其大小可以确定; 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) {
|
According to microsoft, an incomplete type is one whose size can't be determined
那不是 "incomplete type" 的意思。这是适用于不完整类型的 属性。
不完整类型是指尚未定义的类型。示例:
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 的成员函数是另一件不能为不完整类型完成的事情。示例:
class Y; // this is not a definition; Y is incomplete
Y::Y() {} // program is ill-formed because Y is incomplete
回到您的问题:您试图在 bin.cpp 中定义 quadtree
的成员函数,即使 bin.cpp 不包含 quadtree
的定义。 quadtree
必须先定义。只需包含包含定义的 header。
在quadtree.h
中定义结构,但在结构内部您已经在构造函数的内联定义中使用它(quadtree(rect2 bounds): b(b) {}
),这是不允许的,因为它不是尚未完全定义。编译器无法生成构造函数的代码,因为它还不知道还会有多少数据成员。
您可以通过仅声明构造函数来避免此问题:quadtree(rect2 bounds): b(b);
,然后单独(在[=结构的 13=] 添加其定义 template<...> quadtree::quadtree(rect2 bounds) {}
问题在于如何定义属于模板的成员函数 class。
在你的class声明中,你说quadtree
是一个有3个参数的模板,但是当你去定义成员函数时,你只列出了两个。
要修复它,您只需指定模板采用这三个参数:
template<int capacity,
typename t,
typename z>
void quadtree<capacity, t, z>::divide() {
您没有在这里指定第三个参数的默认值,因为您在声明模板时已经这样做了。
作为替代方案,您可以在模板 class 定义中定义内联函数。
请记住,模板 class 定义需要 in the header file,而不是 .cpp 文件。
来自(相当长的)未来的我,解决方案是放弃 std::enable_if
s。我仍然不清楚为什么它们会导致问题,但是在 class 正文中用一个 static_assert
替换它们就足以解决问题。无论如何,孩子们,不要使用这个代码。太可怕了。