2016-09-15 49 views
3

有人可以向我詳細解釋如何使用boost::multi_index創建多索引圖嗎?我在網上看到很多例子,也看到了提升頁面,但我無法理解它。我想通過多個int/longs作爲鍵映射類對象指針。有人可以幫助我理解這一點嗎?如何使用/創建boost :: multi_index?

我有一個類X並且其long longlongintint類的多個屬性。我想將屬性long long,long,int,int作爲映射到的關鍵字 - > <指針指向X >。

我希望能夠查找給定任何屬性的指針。有些屬性對於每個對象X都是唯一的,有些屬性並不是唯一的。

+0

你想要int還是long鍵?或者一個int和一個long在同一時間? –

+2

你需要展示你堅持的東西。由於唯一可能的答案是鏈接到許多有用的在線示例。請參閱http://stackoverflow.com/help/mcve – sehe

+0

我有一個類X和類(long long),(long),(int),(int)的多個屬性。我想存儲<(long long),(long),(int),(int)>作爲映射到的關鍵字 - ><指向X> – quickdraw

回答

6

Boost.Multi-index以提供非常複雜的界面爲代價提供了一個非常可定製的界面,因此很容易理解爲什麼被卡住。

我將介紹一個應該與您的用例相匹配的註釋示例。

首先,我們的數據:

struct X 
{ 
    long long l; // assume unique 
    int i1; // assume unique 
    int i2; // assume non-unique 
    // plus any ohter data you have in your class X 
}; 

接下來,我們將爲此我們希望容器有每個索引準備一個標籤。標籤是沒有嚴格要求(指標可以通過它們的順序訪問),但它更方便地爲每個索引提供了一個名字:

struct IndexByL {}; 
struct IndexByI1 {}; 
struct IndexByI2 {}; 

現在,我們有什麼需要我們放在一起容器的類型:

using Container = boost::multi_index_container< 
    X*, // the data type stored 
    boost::multi_index::indexed_by< // list of indexes 
    boost::multi_index::hashed_unique< //hashed index over 'l' 
     boost::multi_index::tag<IndexByL>, // give that index a name 
     boost::multi_index::member<X, long long, &X::l> // what will be the index's key 
    >, 
    boost::multi_index::ordered_unique< //ordered index over 'i1' 
     boost::multi_index::tag<IndexByI1>, // give that index a name 
     boost::multi_index::member<X, int, &X::i1> // what will be the index's key 
    >, 
    boost::multi_index::hashed_non_unique< //hashed non-unique index over 'i2' 
     boost::multi_index::tag<IndexByI2>, // give that index a name 
     boost::multi_index::member<X, int, &X::i2> // what will be the index's key 
    > 
    > 
>; 

就是這樣,我們有一個容器。接下來,這裏是我們如何使用它:

Container c; // empty container 
X x1{...}, x2{...}, x3{...}; // some data 

// Insert some elements 
auto& indexByL = c.get<IndexByL>(); // here's where index tags (=names) come in handy 
indexByL.insert(&x1); 
indexByL.insert(&x2); 
indexByL.insert(&x3); 

// Look up by i1 
auto& indexByI1 = c.get<IndexByI1>(); 
auto itFound = indexByI1.find(42); 
if (itFound != indexByI1.end()) 
{ 
    X *x = *itFound; 
} 

// Look up by i2 
auto& indexByI2 = c.get<IndexByI2>(); 
size_t numberOfHundreds = indexByI2.count(100); 

[Live example]

而現在,一些散文關於野獸一般是如何工作的。

通過指定它將存儲的對象的類型(您的案例中爲)和一個或多個可用於訪問存儲對象的索引來定義多索引容器。將索引視爲訪問數據的接口。

索引可以是不同的類型:基於由密鑰訂購

  • 指數(認爲std::setstd::map
  • 指數基於通過按鍵排名(想的一樣加上方便地訪問ñ個元素)
  • 索引基於散列基於在穩定順序訪問密鑰(認爲std::unordered_setstd::unordered_map
  • 指標(認爲基於穩定的順序隨機存取)
  • 指數(認爲std::vector

基於密鑰的指標也可以是獨一無二的(如std::map),或者非唯一的(如std::multimap)。

定義容器時,您將想要的每個索引作爲一個模板參數傳遞給boost::multi_index::indexed_by。 (在我們上面的例子中,我添加了三個索引)。

對於不使用密鑰的索引(穩定訂單&隨機訪問),無需指定任何內容;你只是說「我想要這樣一個指數。」

對於基於密鑰的索引,還需要指定如何從數據中獲取密鑰。這是關鍵提取器發揮作用的地方。 (在這個例子中,這是boost::multi_index::member的三種用法)。基本上,對於每個索引,您提供一個用於從存儲在容器中的數據中派生密鑰的配方(或算法)。目前可用的鍵提取是:

  • 使用元素本身:identity
  • 使用元素的數據成員:member
  • 使用元素的(常量)成員函數:[const_]mem_fun
  • 使用全局函數:global_fun
  • 將多個鍵提取到一個:composite_key

請注意,鍵提取器能夠透明地取消引用指針。也就是說,如果您的數據元素是指向類C的指針,則可以指定類C上的鍵提取器,並且解引用將自動發生。 (這個屬性也用在這個例子中)。

這樣就可以定義一個帶索引的容器。要訪問索引,請調用容器上的get成員函數模板。您可以在indexed_by的模板參數列表中通過其序列號引用索引。爲了獲得更多可讀的操作,您可以爲每個索引(或其中的一部分)引入一個標籤。標記是一個任意類型(通常是一個具有合適名稱的空結構),它允許您使用該類型作爲get的模板參數,而不是索引的序列號。 (這也用在這個例子中)。

從容器中檢索到索引的引用後,就可以像索引對應的數據結構一樣使用它(map,hashset,vector,...)。通過該索引完成的更改將影響整個容器。

+0

謝謝!這非常有用。我沒有將這些屬性作爲您所描述的獨立結構。我會將這些屬性作爲X類或其父類派生自其他類的成員。這會改變你答案中的任何事情嗎? – quickdraw

+0

@Ram不,我的意思是'X'是你正在使用的結構。我會澄清答案。 – Angew

+0

謝謝Angew!爲了讓自己更清楚,我希望類對象的指針可以通過屬於其父/父類父類的類的屬性進行索引/映射。 – quickdraw