是的,您可以为此定义适当的函数。
由于您提供的细节非常少,让我们做一些假设。
struct Tree
{
bool isLiana;
void* attachedTree;
Tree* next;
};
using TreePointer = Tree*;
struct Plot
{
TreePointer FirstTree;
Plot* next;
};
using PlotPointer = Plot*;
bool TestForLianaAttach(PlotPointer, TreePointer);
void DoLianaAttachement(PlotPointer, TreePointer);
PlotPointer FirstPlot;
为了让指针正常工作,您需要为指针定义适当的
begin()
和
end()
方法。
NextIterator<Plot> begin(PlotPointer ptr) {return make_NextIterator(ptr);}
NextIterator<Plot> end(PlotPointer) {return make_NextIterator<Plot>();}
NextIterator<Tree> begin(TreePointer ptr) {return make_NextIterator(ptr);}
NextIterator<Tree> end(TreePointer) {return make_NextIterator<Tree>();}
基于范围的 for 循环会寻找能够与您的类型一起使用的
begin()
和
end()
函数。现在,标准库有默认的
std::begin()
和
std::end()
函数,它们会调用对象的
begin()
和
end()
方法。但是,您可以自己提供(如上所述)以针对您的类型/指针执行特殊操作。
现在,由于您的指针使用p = p->next;
来推进,因此我们需要一个迭代器对象来完成这部分工作。在上面的代码中,我称其为NextIterator
。定义它相对容易。
template<typename T>
struct NextIterator
{
T* p;
NextIterator(): p(nullptr) {}
NextIterator(T* ptr): p(ptr) {}
NextIterator& operator++(){p = p->next;return *this;}
T const& operator*() const {return *p;}
T& operator*() {return *p;}
T const* operator->() const {return p;}
T* operator->() {return p;}
bool operator==(NextIterator const& rhs) const {return p == rhs.p;}
bool operator!=(NextIterator const& rhs) const {return p != rhs.p;}
};
template<typename T>
NextIterator<T> make_NextIterator(T* val) {return NextIterator<T>(val);}
template<typename T>
NextIterator<T> make_NextIterator() {return NextIterator<T>{};}
现在我们可以使用基于范围的for循环重写您的循环。
void DoLianaRange(void) {
for(auto& plot: FirstPlot) {
for(auto& tree: plot.FirstTree) {
if (tree.isLiana) {
if (tree.attachedTree == nullptr && TestForLianaAttach(&plot, &tree))
DoLianaAttachement(&plot, &tree);
}
}
}
}
请见以下内容,供参考对比。
void DoLiana(void) {
PlotPointer plot;
TreePointer tree;
plot = FirstPlot;
while (plot != nullptr) {
tree = plot->FirstTree;
while (tree != nullptr) {
if (tree->isLiana) {
if (tree->attachedTree == nullptr && TestForLianaAttach(plot, tree))
DoLianaAttachement(plot, tree);
}
tree = tree->next;
}
plot = plot->next;
}
}
或者您可以简单地使用标准的for循环!
void DoLianaForLoop(void) {
for (PlotPointer plot = FirstPlot; plot != nullptr; plot = plot->next) {
for (TreePointer tree= plot->FirstTree; tree != nullptr; tree = tree->next) {
if (tree->isLiana) {
if (tree->attachedTree == nullptr && TestForLianaAttach(plot, tree))
DoLianaAttachement(plot, tree);
}
}
}
}
将所有代码放在一个地方(按正确顺序编译)。
struct Tree
{
bool isLiana;
void* attachedTree;
Tree* next;
};
using TreePointer = Tree*;
struct Plot
{
TreePointer FirstTree;
Plot* next;
};
using PlotPointer = Plot*;
template<typename T>
struct NextIterator
{
T* p;
NextIterator(): p(nullptr) {}
NextIterator(T* ptr): p(ptr) {}
NextIterator& operator++(){p = p->next;return *this;}
T const& operator*() const {return *p;}
T& operator*() {return *p;}
T const* operator->() const {return p;}
T* operator->() {return p;}
bool operator==(NextIterator const& rhs) const {return p == rhs.p;}
bool operator!=(NextIterator const& rhs) const {return p != rhs.p;}
};
template<typename T>
NextIterator<T> make_NextIterator(T* val) {return NextIterator<T>(val);}
template<typename T>
NextIterator<T> make_NextIterator() {return NextIterator<T>{};}
NextIterator<Plot> begin(PlotPointer ptr) {return make_NextIterator(ptr);}
NextIterator<Plot> end(PlotPointer) {return make_NextIterator<Plot>();}
NextIterator<Tree> begin(TreePointer ptr) {return make_NextIterator(ptr);}
NextIterator<Tree> end(TreePointer) {return make_NextIterator<Tree>();}
bool TestForLianaAttach(PlotPointer, TreePointer);
void DoLianaAttachement(PlotPointer, TreePointer);
PlotPointer FirstPlot;
void DoLianaRange(void) {
for(auto& plot: FirstPlot) {
for(auto& tree: plot.FirstTree) {
if (tree.isLiana) {
if (tree.attachedTree == nullptr && TestForLianaAttach(&plot, &tree))
DoLianaAttachement(&plot, &tree);
}
}
}
}
void DoLiana(void) {
PlotPointer plot;
TreePointer tree;
plot = FirstPlot;
while (plot != nullptr) {
tree = plot->FirstTree;
while (tree != nullptr) {
if (tree->isLiana) {
if (tree->attachedTree == nullptr && TestForLianaAttach(plot, tree))
DoLianaAttachement(plot, tree);
}
tree = tree->next;
}
plot = plot->next;
}
}
std::list
或std::slist
来满足您的链表需求 - 这些类已经提供了必要的脚手架。 - Igor Tandetnikbegin
和end
方法,该方法将返回具有定义了operator++()
和operator==
的对象。我认为一个简单的指针就可以胜任。@IgorTandetnik 我认为 begin/end 返回的类型甚至不需要正式成为迭代器。 - luk32for (PlotPointer plot = FirstPlot; plot != nullptr; plot=plot.next) { for (TreePointer tree = plot->FirstTree, tree!= nullptr; tree=tree->next) { ... }}
。 - Serge Ballesta++
不起作用。这就为实现一个迭代器提供了一个非常好的练习机会。 - luk32