我有一个 Foo* 类型的 std::list 和另一个大小不等的 Bar* 类型。这两种类型都实现了一个定位系统,允许列表按绘制顺序的 z 坐标排序(实际上只是一个具有 x、y、z 值的点,它们按 z 值使用小于谓词函数排序)。
除了上面提到的,它们是完全不同的。有没有一种方法可以组合列表,以便我可以将所有 z 值相互比较,而不仅仅是它们自己的类型?
现在,例如,要么所有 Foos 都已排序,要么所有 Bars 都已排序;然后要么绘制所有 Foos,要么绘制所有 Bars。这使得即使 Bar 的 z 比 Foo 低,它也会被绘制在顶部。显然不是预期的结果。
打字时我突然顿悟,并行处理可行吗?分别对每个列表进行排序,然后交替绘制它们,Foo、Bar、Foo、Bar 等,否则会导致同样的问题吗?不管 z 值如何,有些绘图高于其他绘图?
谢谢。
最佳答案
您可以尝试让这两种类型都继承自包含位置的基类,或许可以使用 virtual Draw()
:
struct Base
{
Point pos;
virtual ~Base() {}
virtual void Draw() = 0;
};
struct Foo : base {};
struct Bar : base {};
std::list<Base*> list;
//...
list.sort([](Base *left, Base *right)
{
return left->pos.z < right->pos.z;
});
for(auto iter = list.begin(), end = list.end(); iter != end; ++iter)
{
(*iter)->Draw();
}
如果你想保持列表分开,如果 Foo
中的两个有出现在一个 Bar
之前。
但您的思路是正确的。您可以单独排序,然后在绘制时合并两个列表:
foo_list.sort();
bar_list.sort();
auto fiter = foo_list.begin(), fend = foo_list.end();
auto biter = bar_list.begin(), bend = bar_list.end();
while(fiter != fend && biter != bend)
{
// draw whichever Foo or Bar is closest, and increment only that iterator.
if((*fiter)->z_pos < (*biter)->z_pos)
{
(*fiter)->Draw();
++fiter;
}
else
{
(*biter)->Draw();
++biter;
}
}
// reached the end of one of the lists. flush out whatever's left of the other.
for(; fiter != fend; ++fiter)
{
(*fiter)->draw();
}
for(; biter != bend; ++biter)
{
(*biter)->draw();
}
如果您只想保留一个列表但有两个完全独立的类型,您也可以使用变体:
struct visitor
{
float operator()(Foo* f) const { return f->z_position; }
float operator()(Bar* b) const { return b->z_position; }
};
std::list<boost::variant<Foo*, Bar*>> list;
//...
list.sort([](boost::variant<Foo*, Bar*> const &left, boost::variant<Foo*, Bar*> const &right)
{
return apply_visitor(visitor(), left) < apply_visitor(visitor(), right);
});
for(auto iter = list.begin(), end = list.end(); iter != end; ++iter)
{
(*iter)->Draw();
}
关于c++ - 组合两个不同类型的 std::lists:可能吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6577784/