boost - 查找 boost multi index 标签到索引和索引数量

标签 boost boost-multi-index

我有一个模板类(CrMultiIndex),它接收 boost 多索引(GlobalHash)的定义作为模板参数。

我需要:

  1. 根据使用的索引向我的模板类添加统计信息。 所以我需要一种方法在初始化时使用现有索引的数量调整向量(m_StatsByIndex)的大小。
  2. 我仍然希望用户根据标签而不是索引号进行搜索。 所以我需要一种从标签转换为索引号的方法,这样我就可以根据向量中的索引更新向量中的统计信息。

我有模板类

template <typename KeysType, typename MultiIndexType>
class CrMultiIndex
{

std::vector<SrStatisticsByIndex> m_StatsByIndex;

public:
MultiIndexType *m_pMultiIndex=NULL; 

CrMultiIndex()
{
    m_pMultiIndex = new MultiIndexType(typename 
    MultiIndexType::ctor_args_list());
}

以下是boost多索引容器的定义:

typedef boost::multi_index::multi_index_container<
  CrUsersKeys,
  UsersKey_hash_indices/*,
  bip::allocator<CrUsersKeys,bip::managed_shared_memory::segment_manager>*/
> GlobalHash;

具有根据Tag搜索功能

template <typename TagType,typename SearchingKey>
typename MultiIndexType::template index<TagType>::type::iterator  
GetIteratorBy(SearchingKey & key)
{
    return  m_pMultiIndex->template get<TagType>().find(key) ;
}

代码位于 http://coliru.stacked-crooked.com/a/d97195a6e4bb7ad4

最佳答案

您需要查询嵌入的索引类型列表:

typedef typename MultiIndexType::index_type_list::size NumberOfIndexes;

template <typename Tag> constexpr static size_t IndexOfTag() {
    namespace mpl = boost::mpl;
    using tl = typename MultiIndexType::index_type_list;
    using B  = typename mpl::begin<tl>::type;
    using helper = typename MultiIndexType::template index<Tag>;
    static_assert(helper::index_found, "index not found");
    auto N = mpl::distance<B, typename helper::iter>::value;
    return N;
}

或者,一直使用 Boost Mpl:

typedef typename MultiIndexType::index_type_list::size NumberOfIndexes;

template <typename Tag> constexpr static size_t IndexOfTag() {
    namespace mpl = boost::mpl;
    using tl = typename MultiIndexType::index_type_list;
    using B  = typename mpl::begin<tl>::type;
    using E  = typename mpl::end<tl>::type;
    using It = typename mpl::find_if<tl, bmi::detail::has_tag<Tag> >::type;
    static_assert(not std::is_same<E, It>(), "index not found");
    auto N = mpl::distance<B, It>::value;
    return N;
}

你可以像这样使用它:

template <typename TagType, typename SearchingKey>
    typename MultiIndexType::template index<TagType>::type::iterator 
GetIteratorBy(SearchingKey &key) {
    auto& idx   = m_pMultiIndex.template get<TagType>();
    auto& stats = GetStats<TagType>();

    auto it = idx.find(key);
    ++(it == idx.end()? stats.searchedNotFound : stats.searchedSuccessfully);

    return it;
}

演示

请注意,代码已被简化:

Live On Coliru

#include <iostream>
#include <boost/multi_index/member.hpp>           // for member
#include <boost/multi_index/hashed_index.hpp>     // for hashed_unique
#include <boost/multi_index/ordered_index.hpp>    // for ordered_non_unique
#include <boost/multi_index_container.hpp>        // for multi_index_container

namespace bmi = boost::multi_index;

struct SrStatisticsByIndex {
    int deleted;
    int searchedSuccessfully;
    int searchedNotFound;
};

template <typename MultiIndexType, typename ValueType = typename MultiIndexType::value_type> 
class CrMultiIndex {

    typedef typename MultiIndexType::index_type_list::size NumberOfIndexes;

    template <typename Tag> constexpr static size_t IndexOfTag() {
        using tl = typename MultiIndexType::index_type_list;
        using B  = typename boost::mpl::begin<tl>::type;
        using helper = typename MultiIndexType::template index<Tag>;
        static_assert(helper::index_found, "index not found");

        return boost::mpl::distance<B, typename helper::iter>::value;
    }

  public:
    MultiIndexType m_pMultiIndex;

    template <typename Tag> SrStatisticsByIndex& GetStats()
        { return m_StatsByIndex.at(IndexOfTag<Tag>()); }

    template <typename Tag> SrStatisticsByIndex const& GetStats() const
        { return m_StatsByIndex.at(IndexOfTag<Tag>()); }

    // All the protected function are non locking function
    template <typename TagType, typename SearchingKey>
        typename MultiIndexType::template index<TagType>::type::iterator 
    GetIteratorBy(SearchingKey &key) {
        auto& idx   = m_pMultiIndex.template get<TagType>();
        auto& stats = GetStats<TagType>();

        auto it = idx.find(key);
        ++(it == idx.end()? stats.searchedNotFound : stats.searchedSuccessfully);

        return it;
    }

    void Insert(ValueType const &key) {
        std::cout << (m_pMultiIndex.insert(key).second? "success":"failed") << std::endl;
    }

  private:
    std::vector<SrStatisticsByIndex> m_StatsByIndex { NumberOfIndexes() };
};

class CrUsersValue {
    int val1;
    int val2;
};

class CrUsersKeys {
  public:
    int IMSI;
    int TIMESTAMP;
    CrUsersValue val;
};

typedef boost::multi_index::multi_index_container<
        CrUsersKeys,
        bmi::indexed_by<
            bmi::ordered_non_unique<bmi::tag<struct TIMESTAMP_tag>,
                                    bmi::member<CrUsersKeys, int, &CrUsersKeys::TIMESTAMP> >,
            bmi::hashed_unique<bmi::tag<struct IMSI_tag>,
                               bmi::member<CrUsersKeys, int, &CrUsersKeys::IMSI> /*, boost::hash<int>, std::equal_to<int>*/>
        >
        /*, bip::allocator<CrUsersKeys,bip::managed_shared_memory::segment_manager>*/
    >
    GlobalHash;

int main() {
    CrMultiIndex<GlobalHash> multi;

    CrUsersKeys key;
    key.IMSI = 2;
    multi.Insert(key);

    int searchKey = 2;
    auto it = multi.GetIteratorBy<IMSI_tag>(searchKey);
    if (it != multi.m_pMultiIndex.get<IMSI_tag>().end())
        std::cout << "found " << std::endl;
}

打印

success
found 

关于boost - 查找 boost multi index 标签到索引和索引数量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49232257/

相关文章:

c++ - 从 equal_range 查询过滤和修改 boost::multi_index 中的元素

c++ - 有没有一种方法可以插入具有多个提示的 boost::multi_index ?

c++ - 用 Boost::Test 模拟

c++ - Boost 编译在 boost/move/unique_ptr.hpp 中失败

c++ - 提取大型库的小部分(fx boost)

c++ - 将 boost::multi_index 与复合键成员函数一起使用时出现问题

c++ - boost的多索引是否复制键对象

c++ - 为什么 make_nvp 需要非常量引用?

c++ - Boost 1.46.1,属性树 : How to iterate through ptree receiving sub ptrees?

c++ - 通过索引快速搜索并保持 C++ 中的插入顺序