簡體   English   中英

結合兩個不同類型的 std::lists:可能嗎?

[英]Combining two std::lists of differing types: Possible?

我有一個 Foo* 類型的 std::list 和另一個大小不等的 Bar* 類型。 兩種類型都實現了一個定位系統,允許列表按 z 坐標排序以獲取繪制順序(實際上只是一個具有 x、y、z 值的點,它們按 z 值小於 Predicate function 進行排序)。

除了上面提到的,它們是完全不同的。 有沒有辦法組合列表,以便我可以將所有 z 值相互比較,而不僅僅是它們自己的類型?

現在,例如,要么所有 Foo 都已排序,要么所有 Bar 都已排序; 然后要么繪制所有 Foos,要么繪制所有 Bars。 這使得即使 Bar 的 z 比 Foo 低,它也會被繪制在頂部。 顯然不是預期的結果。

在打字時我確實有一個頓悟,並行處理會起作用嗎? 分別對每個列表進行排序,然后交替繪制它們,Foo、Bar、Foo、Bar 等,還是會導致同樣的問題? 無論z值如何,有些人在其他人之上繪圖?

謝謝。

您可以嘗試讓這兩種類型都從包含 position 的基礎繼承,可能使用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之前,則交替繪制FooBar將不起作用。

但你的想法是正確的。 您可以單獨排序,然后在繪圖時合並兩個列表:

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();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM