29 Mayıs 2018 Salı

multi_index ordered_unique Sınıfı

Giriş
Şu satırı dahil ederiz.
#include <boost/multi_index/ordered_index.hpp>
std::set gibidir.

Kolay kullanım için şu satırı dahil ederiz.
namespace bmi = boost::multi_index;
Tanımlama - tag + member field
Şu satırı dahil ederiz.
#include <boost/multi_index/member.hpp>
Örnek
Şöyle yaparız.
struct Foo
{
  int id;
  std::string name;
};

struct id_tag { };
struct name_tag { };

boost::multi_index_container<  
  Foo,
  bmi::indexed_by<
    bmi::ordered_unique<
      bmi::tag<id_tag>, 
      bmi::member<Foo, int, &Foo::id>
    >,
  ...
>;
Örnek
Şöyle yaparız
template<typename KeyType, typename MappedType>
struct LinkedMap {
  typedef std::pair<KeyType, MappedType> value_type;
  typedef boost::multi_index_container<
    value_type,
    boost::multi_index::indexed_by<
      ... 
      boost::multi_index::ordered_unique<
        boost::multi_index::member<value_type, KeyType, &value_type::first>
      >
    >
  > type;
};
Örnek
Eğer istersek tag'i dışarıda tanımlamak yerine yerinde de tanımlayabiliriz. Şöyle yaparız.
bmi::ordered_unique<
  bmi::tag<struct id_tag>,  bmi::member<...>
>
Tanımlama - member fields as composite key
Şu satırı dahil ederiz.
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/composite_key.hpp>
#include <boost/multi_index/member.hpp>
Elimizde şöyle bir yapı olsun.
struct Foo {
  std::string firstname;
  std::string lastname;
  Foo(const std::string & firstname, const std::string & lastname) :
     firstname(firstname), lastname(lastname) {}
};
Şöyle yaparız.
typedef boost::multi_index::multi_index_container<
  Foo,
  boost::multi_index::indexed_by<
    boost::multi_index::ordered_unique<
      boost::multi_index::composite_key<
        Foo,
        boost::multi_index::member<Foo, std::string, &Foo::lastname>,
        boost::multi_index::member<Foo, std::string, &Foo::firstname>
      >,
      boost::multi_index::composite_key_compare<
        std::less<std::string>,
        std::less<std::string>
      >
    >
  >
> Container;
find metodu
Şöyle yaparız.
Container c = ...;

// Look up by i1
auto& indexByI1 = c.get<IndexByI1>();
auto itFound = indexByI1.find(42);
if (itFound != indexByI1.end())
{
  X *x = *itFound;
}
lower_bound metodu
Örnek
İndeks için tag tanımlanmamışsa şöyle yaparız.
auto it = c.get<0>().lower_bound(
    c.get<0>().key_extractor()(foo));
Örnek
İndeksi tag ile bulduktan sonra şöyle yaparız.
struct TPQ {...};

using Rank_Set = bmi::multi_index_container<
    TPQ,
    bmi::indexed_by<
        bmi::ordered_unique<
            bmi::tag<struct RankFilterView>,
            bmi::composite_key<TPQ,
                bmi::member<TPQ, int, &TPQ::UID>, 
                bmi::member<TPQ, int, &TPQ::Value>,
                bmi::member<TPQ, int, &TPQ::Rank>
            >
        >
    >,
>;

using Rank_view = bmi::index<Rank_Set, RankFilterView>::type;

auto& table = ...;

table.insert({
  {52478, 501, 6}, // Match!
  {52478, 500, 6}, // - Value too small
  {52479, 0,   0}, // - UID too high
  {52478, 502, 6}, // Match!
  {52478, 502, 7}, // Match!
  {52478, 501, 5}, // - Rank too small
  {52477, 502, 7}, // - UID too small
  {52478, 999, 9}, // Match!
});

int UID = 52478;
Rank_view& view = table.get<RankFilterView>(); 

auto range = boost::make_iterator_range(
  view.lower_bound(boost::make_tuple(UID, 501, 6)),
  view.lower_bound(boost::make_tuple(UID+1)));
...   
modify metodu
Saklanan tip şöyle olsun ve index pair'in first alanı olsun.
std::pair<int, std::wstring>;
Şöyle yaparız.
auto& idToNameMap = userMap.get<1>();
auto& iter = idToNameMap.find(1);
if(iter != idToNameMap.end()) {
   idToNameMap.modify(iter, [](auto& p){p->second = "Tom";});
} 
replace metodu
Şöyle yaparız.
auto overwrite = [&](int key, auto&& val)
{
  auto& idToNameMap = userMap.get<by_key>();
  auto iter = idToNameMap.find(key);
  if (iter == idToNameMap.end())
  {
    auto ib = userMap.push_back(std::make_pair(1, std::forward<decltype(val)>(val)));
    assert(ib.second);
  }
  else
  {
    idToNameMap.replace(iter, 
      std::make_pair(key, std::forward<decltype(val)>(val)));
    }
};