2009-08-24 29 views
3

我正在尋找一個帶有組合鍵的增強ordered_non_unique索引的自定義比較器。我不確定如何做到這一點。 Boost有composite_key_comparer,但這對我不起作用,因爲密鑰成員之一的比較器取決於以前的成員。這是一個簡化的例子,但我希望third_上的索引按third_降序排列,當second_爲'A'時,首先保留third_的0值,並在所有其他情況下使用std :: less。希望這是有道理的。我想下面的代碼打印出:增強多索引自定義複合鍵比較器

3,BLAH,A,0 
5,BLAH,A,11 
2,BLAH,A,10 
4,BLAH,A,9 
1,BLAH,A,8 

的代碼會去的地方善有善報HERE ???。謝謝你的幫助。

#include <boost/multi_index_container.hpp> 
#include <boost/multi_index/key_extractors.hpp> 
#include <boost/multi_index/ordered_index.hpp> 
#include <boost/multi_index/composite_key.hpp> 
#include <iostream> 

namespace bmi = boost::multi_index; 
namespace bt = boost::tuples; 

struct Widget 
{ 
    Widget (const std::string& id, const std::string& f, char s, unsigned int t) 
    : id_(id) 
    , first_(f) 
    , second_(s) 
    , third_(t) 
    { } 

    ~Widget() { } 

    std::string id_; 
    std::string first_; 
    char second_; 
    unsigned int third_; 
}; 

std::ostream& operator<< (std::ostream& os, const Widget& w) 
{ 
    os << w.id_ << "," << w.first_ << "," << w.second_ << "," << w.third_; 
    return os; 
} 

struct id_index { }; 
struct other_index { }; 

typedef bmi::composite_key< 
    Widget*, 
    bmi::member<Widget, std::string, &Widget::first_>, 
    bmi::member<Widget, char, &Widget::second_>, 
    bmi::member<Widget, unsigned int, &Widget::third_> 
> other_key; 

typedef bmi::multi_index_container< 
    Widget*, 
    bmi::indexed_by< 
    bmi::ordered_unique< 
     bmi::tag<id_index>, 
     bmi::member<Widget, std::string, &Widget::id_> 
    >, 
    bmi::ordered_non_unique< 
     bmi::tag<other_index>, 
     other_key, 
     ***************WHAT GOES HERE???*************** 
    > 
    > 
> widget_set; 

typedef widget_set::index<other_index>::type widgets_by_other; 
typedef widgets_by_other::iterator other_index_itr; 

int main() 
{ 
    widget_set widgets; 
    widgets_by_other& wbo_index = widgets.get<other_index>(); 
    Widget* w; 

    w = new Widget("1", "BLAH", 'A', 8); 
    widgets.insert(w); 
    w = new Widget("2", "BLAH", 'A', 10); 
    widgets.insert(w); 
    w = new Widget("3", "BLAH", 'A', 0); 
    widgets.insert(w); 
    w = new Widget("4", "BLAH", 'A', 9); 
    widgets.insert(w); 
    w = new Widget("5", "BLAH", 'A', 11); 
    widgets.insert(w); 

    std::pair<other_index_itr,other_index_itr> range = 
    wbo_index.equal_range(boost::make_tuple("BLAH", 'A')); 

    while (range.first != range.second) 
    { 
    std::cout << *(*range.first) << std::endl; 
    ++range.first; 
    } 

    return 0; 
} 

回答

3

我想你已經撞上了牆。

你可能想在這裏提及:Ordered Indices

如同STL,你實際上必須自己提供的比較標準,這樣的話你必須把它符合您的需要的能力。

有序索引的說明書的最後一部分是相關聯的比較謂詞,必須以較低的命令的鍵:

作爲頁I連接的(在「比較謂詞」部分)上解釋 - 比時尚。

因此,你的工作是雙重的:

  1. 您需要定義一個合適的比較謂詞,這對你的工作類型
  2. 您需要指示Boost.MultiIndex的,你想使用此謂詞進行鍵的實際比較

下面是一個示例,我不確定我是否完全理解了您的要求,但是您可能必須檢查它是否按您的意願進行排序。

struct WidgetComparer 
{ 
    bool operator()(const Widget& lhs, const Widget& rhs) const 
    { 
    if (lhs._second == 'A' && rhs._second == 'A') 
    { 
     return lhs._third == 0 || rhs._third < lhs._third; 
    } 
    else 
    { 
     return lhs._third < rhs._third; 
    } 
    } // operator() 
}; 

然後,你只需要完成你的索引。所以用身份< Widget>和「什麼在這裏」替換「其他關鍵」WidgetComparer

在這裏你去!

重要的一點是,你不應該集中在集裝箱的「關鍵」的一部分。關鍵沒有什麼本身,它是做實際排序的夫婦(關鍵,比較謂詞)。重點是文檔,以增強代碼重用在鍵(和特別地,涉及從被比如std ::少已經實施的比較謂詞受益)。

作爲替代方案,你可以決定你的Widget類編寫一個「經營者<」或特殊化的std ::少算法。如果你打算使用排序不止一次的這樣,你應該更喜歡這種解決方案。但是,如果您的容器是唯一使用它的容器,那麼自定義謂詞更好。

希望有幫助。