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::set
或std::map
)
- 指數基於通過按鍵排名(想的一樣加上方便地訪問ñ個元素)
- 索引基於散列基於在穩定順序訪問密鑰(認爲
std::unordered_set
或std::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,...)。通過該索引完成的更改將影響整個容器。
你想要int還是long鍵?或者一個int和一個long在同一時間? –
你需要展示你堅持的東西。由於唯一可能的答案是鏈接到許多有用的在線示例。請參閱http://stackoverflow.com/help/mcve – sehe
我有一個類X和類(long long),(long),(int),(int)的多個屬性。我想存儲<(long long),(long),(int),(int)>作爲映射到的關鍵字 - ><指向X> – quickdraw