Giriş
Şu satırı dahil ederiz.
Şöyle yaparız
Şöyle yaparız.
Şu satırı dahil ederiz.
#include <boost/multi_index_container.hpp>
TanımlamaŞöyle yaparız
typedef multi_index_container<
Foo,
indexed_by<
...
>
> ContainerType;
Tag ile TanımlamaŞöyle yaparız.
struct id_tag { };
struct name_tag { };
typedef multi_index_container< Foo,
boost::multi_index::indexed_by<
boost::multi_index::ordered_unique<
boost::multi_index::tag<id_tag>, ... >,
boost::multi_index::ordered_unique<
boost::multi_index::tag<name_tag>, ... >
>
>;
Kalıtım
Önce bir template tanımlarız. Şöyle yaparız
Sonra template için parametreleri şöyle tanımlarız.template <class D, class E>
classa MyContainer : public boost::multi_index_container<D, E>
{...};
// Requires -std=c++11
using FooContainer = MyContainer<
Foo,
boost::multi_index::indexed_by<...>
>;
Sonra bu sınıfı ilklendiririz.FooContainer items;
Constructor
Constructor - iterator + iterator
Şöyle yaparız.
Elimizde shared_ptr içeren bir multi_index olsun
ÖrnekŞöyle yaparız.
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/sequenced_index.hpp>
#include <boost/multi_index/ordered_index.hpp>
namespace bmi = boost::multi_index;
using Index = bmi::multi_index_container<char,
bmi::indexed_by<
bmi::sequenced<>,
bmi::ordered_unique<bmi::tag<struct unique>, bmi::identity<char> >
> > ;
auto const str = ...;
Index idx(str.begin(), str.end());
Constructor - variadic templateElimizde shared_ptr içeren bir multi_index olsun
namespace bmi = boost::multi_index;
using Table = bmi::multi_index_container<moveonly,
bmi::indexed_by<
bmi::random_access<bmi::tag<struct _ra> >
> >;
Bu sınıfı variadic olarak ilklendiren bir metod olsun.template <typename V, typename... Init>
auto make_bmi_set(Init&&... values) {
return Table<std::string> {
std::make_shared<V>(std::forward<Init>(values))...
};
}
Şöyle yaparız.auto items = make_bmi_set<std::string>("one", "two", "three", "four", "Hungary");
erase metoduŞöyle yaparız.
auto it = table.begin();
if (it == table.end())
throw std::logic_error("...");
table.erase(it);
erase metodu - it + itÖrnek
Şöyle yaparız.
it begin = ...; it end = ...;
c.erase(begin,end);
get metodu - int sıra numarası
İndekslere get() metodu ile erişilir. Şöyle yaparız.
İndekslere tag ile erişilir. Şöyle yaparız.
Şöyle yaparız.
İndeksi mevcut bir indeks ile aynı hale getirince elemanın silinmesi gerekir. Şöyle yaparız.
Bir index iteratörünü bir başka indeks iteratörüne çevirir. Örnek bir LRU cache. Önce eleman hash_index ile bulunuyor. Daha sonra hash_index iterator, container.project() ile sequenced_iterator tipine çevriliyor. sequenced_index elemanı kendi içinde relocate() ile en sona taşıyor.
size metodu
itemContainer::nth_index<0>::type & sequentialItems = items.get<O>();
itemContainer::nth_index<1>::type & associativeItems = items.get<1>();
get metodu - tagİndekslere tag ile erişilir. Şöyle yaparız.
auto& by_id_tag = items.get<id_tag>();
insert metoduŞöyle yaparız.
container.insert(container.end(),foo);
modify metodu
Hem indekslenen hem de indekslenmeyen veriyi değiştirmek için kullanılır.
Boost 1.66'dan önceki açıklaması şöyle. Yani modify() içinde exception fırlatmamak lazım.
Örnek
Şöyle yaparız.
Boost 1.66'dan önceki açıklaması şöyle. Yani modify() içinde exception fırlatmamak lazım.
Modify expects the user-provided modifier not to throw unless it doesn't change the keys of the elements, in which case undefined behavior ensues.Sonrasında eğer exception fırlatılırsa da eleman silinir hale getirildi.
Örnek
Şöyle yaparız.
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/random_access_index.hpp>
#include <iostream>
struct moveonly {
...
};
namespace bmi = boost::multi_index;
using Table = bmi::multi_index_container<moveonly,
bmi::indexed_by<
bmi::random_access<bmi::tag<struct _ra> >
> >;
Table table = ...;
auto it = table.begin();
if (table.modify(it, [&](moveonly& v) { ... })) {
table.erase(it);
}
Örnekİndeksi mevcut bir indeks ile aynı hale getirince elemanın silinmesi gerekir. Şöyle yaparız.
struct employee {
int id;
std::string name;
}
typedef multi_index_container<
employee,
indexed_by<
ordered_unique<BOOST_MULTI_INDEX_MEMBER(employee,int,id)>>
>
> employee_set;
employee_set es;
es.insert(employee{0,"Joe"});
es.insert(employee{1,"Carl"});
es.insert(employee{2,"Robert"});
es.insert(employee{4,"John"});
try {
auto it = es.find(4); // John
es.modify(it, [](auto& employee) {
employee.id = 1; // Same ID of Carl, should be erased
});
} catch (const std::runtime_error& err) {
// handle error...
}
İşlemden sonra çıktı olarak şunu alırız.0 Joe
1 Carl
2 Robert
projectBir index iteratörünü bir başka indeks iteratörüne çevirir. Örnek bir LRU cache. Önce eleman hash_index ile bulunuyor. Daha sonra hash_index iterator, container.project() ile sequenced_iterator tipine çevriliyor. sequenced_index elemanı kendi içinde relocate() ile en sona taşıyor.
using namespace boost::multi_index;
typedef boost::multi_index_container
<
item_t,
boost::multi_index::indexed_by
<
hashed_unique<boost::multi_index::member<item_t,Key,&item_t::key> >,
sequenced<>
>
> cache_t;
enum index_idx
{
e_map = 0,
e_seq = 1,
};
cache_t cache_;
bool find(const Key& key, T& t)
{
typename cache_t::nth_index<e_map>::type& hash_index = cache_.get<e_map>();
auto itr = hash_index.find(key);
if (itr != hash_index.end())
{
return false;
}
t = itr->t;
typename cache_t::nth_index<e_seq>::type& sequenced_index = cache_.get<e_seq>();
auto itr2 = cache_.project<e_seq>(itr);
sequenced_index.relocate(itr2,sequenced_index.end());
return true;
}
Hiç yorum yok:
Yorum Gönder