查找提升多索引标记索引和索引数

时间:2018-03-12 09:50:18

标签: boost boost-multi-index

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

我需要:

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

    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

2 个答案:

答案 0 :(得分:3)

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

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 

答案 1 :(得分:2)

作为sehe答案的补充,这是Response.ItemsBean item = (Response.ItemsBean) getItem(i); TextView txt; txt.setText(item.getCodec().get(i).getSell()); 的重写,不依赖于未记录的Boost.MultiIndex功能:

<强> Live On Coliru

IndexOfTag

编辑:在C ++ 14中:

<强> Live On Coliru

template<typename MultiIndexContainer,std::size_t N=0>
struct index_position:index_position<MultiIndexContainer,N+1>
{
  using index_type=typename boost::multi_index::nth_index<MultiIndexContainer,N>::type;
  using index_position<MultiIndexContainer,N+1>::case_of;
  static constexpr std::size_t case_of(std::in_place_type_t<index_type>){return N;}
};

template<typename MultiIndexContainer>
struct index_position<
  MultiIndexContainer,
  boost::mpl::size<typename MultiIndexContainer::index_type_list>::value
>
{
  static constexpr void case_of(...){}
};

template <typename MultiIndexContainer,typename Tag>
constexpr std::size_t IndexOfTag()
{
  using index_type=typename boost::multi_index::index<MultiIndexContainer,Tag>::type;
  return index_position<MultiIndexContainer>::case_of(std::in_place_type<index_type>);
}