如何遍历Boost Multi Index指定条目的所有索引成员?
实现Boost Multi Index条目所有索引成员的遍历校验
嘿,这个需求我刚好处理过!Boost.MultiIndex本身并没有直接提供遍历单个条目所有索引成员的现成方法,但咱们可以借助C++的元编程和Boost库自带的类型特性来实现,思路很清晰——把容器的每个索引和对应的类成员映射起来,然后逐个提取校验。
第一步:补全容器的完整定义(明确索引结构)
先把你提到的容器定义补全,方便后续演示(假设你的两个索引分别是基于IMSI的唯一有序索引,和基于TIMESTAMP的非唯一有序索引):
#include <boost/multi_index_container.hpp> #include <boost/multi_index/ordered_index.hpp> #include <boost/multi_index/member.hpp> #include <iostream> // 定义索引标签 struct IMSI_tag {}; struct TIMESTAMP_tag {}; class CrUsersKeys { public: int IMSI; int TIMESTAMP; // 构造函数方便初始化 CrUsersKeys(int imsi, int ts) : IMSI(imsi), TIMESTAMP(ts) {} }; // 定义Multi Index容器类型 using UserKeysContainer = boost::multi_index::multi_index_container< CrUsersKeys, boost::multi_index::indexed_by< // 第一个索引:按IMSI唯一排序,标签IMSI_tag boost::multi_index::ordered_unique< boost::multi_index::tag<IMSI_tag>, boost::multi_index::member<CrUsersKeys, int, &CrUsersKeys::IMSI> >, // 第二个索引:按TIMESTAMP非唯一排序,标签TIMESTAMP_tag boost::multi_index::ordered_non_unique< boost::multi_index::tag<TIMESTAMP_tag>, boost::multi_index::member<CrUsersKeys, int, &CrUsersKeys::TIMESTAMP> > > >;
第二步:编写元编程工具提取索引对应的成员指针
Boost.MultiIndex的每个索引都自带key_from_value类型,对于member类型的索引,这个类型里有一个静态成员member,直接指向对应的类成员指针。我们可以写一个简单的元函数来提取这个指针:
// 元函数:从索引类型中提取对应的类成员指针 template <typename IndexType> struct IndexMemberExtractor { // 直接获取member索引的成员指针 static constexpr auto value = typename IndexType::key_from_value::member; };
第三步:编写递归遍历校验函数
利用C++17的constexpr if和递归模板,我们可以遍历容器的所有索引,逐个提取对应成员并校验:
// 示例校验函数:你可以替换成自己的校验逻辑 bool isGood(int value) { return value > 0; // 这里假设值大于0即为有效 } // 递归遍历所有索引的内部辅助函数 template <typename Container, size_t IndexIdx = 0> void validateIndexedMembers(const typename Container::iterator& entryIt) { // 终止条件:遍历完所有索引就停止 if constexpr (IndexIdx == Container::n_indices) { return; } // 获取当前索引的类型 using CurrentIndex = typename Container::template nth_index<IndexIdx>::type; // 获取当前索引对应的类成员指针 constexpr auto memberPtr = IndexMemberExtractor<CurrentIndex>::value; // 提取当前条目的该成员值 const auto& memberValue = (*entryIt).*memberPtr; // 执行你的校验逻辑 if (isGood(memberValue)) { std::cout << "✅ 索引" << IndexIdx << "对应的成员值[" << memberValue << "]校验通过" << std::endl; } else { std::cerr << "❌ 索引" << IndexIdx << "对应的成员值[" << memberValue << "]校验失败" << std::endl; } // 递归处理下一个索引 validateIndexedMembers<Container, IndexIdx + 1>(entryIt); } // 对外暴露的接口函数:先判断迭代器有效性,再启动遍历 template <typename Container> void validateAllIndexedMembers(const typename Container::iterator& entryIt) { if (entryIt == Container().end()) { std::cerr << "⚠️ 传入的迭代器无效!" << std::endl; return; } validateIndexedMembers<Container>(entryIt); }
第四步:使用示例
现在你就可以用你原来的查找逻辑拿到迭代器,然后调用校验函数了:
int main() { UserKeysContainer multi; // 插入测试数据 multi.insert(CrUsersKeys(123456, 1718000000)); // 通过IMSI_tag查找目标条目 int searchKey = 123456; auto it = multi.get<IMSI_tag>().find(searchKey); // 遍历校验该条目所有被索引的成员 validateAllIndexedMembers<UserKeysContainer>(it); return 0; }
关键说明
- 这个方案只针对基于member的索引有效,如果你的索引是复合索引(
composite_key)或者自定义提取器,需要调整IndexMemberExtractor的逻辑来适配 - 用
constexpr在编译期完成成员指针的提取,完全没有运行时额外开销 - 递归遍历的终止条件用
Container::n_indices,这个是Boost.MultiIndex容器自带的静态常量,代表容器的索引总数
内容的提问来源于stack exchange,提问作者yaron
相关产品推荐
相关产品推荐

