Boost.MultiIndex是否支持同一元素在单个索引下对应多个键值?
结论
你提出的需求完全可以通过Boost.MultiIndex实现,无需自行开发自定义数据存储。
实现核心思路
Boost.MultiIndex支持多值键提取器,允许单个元素在同一个索引下对应多个键值,正好匹配你一个学生加入多个俱乐部、需要通过任意俱乐部名称检索到该学生的场景。
代码实现示例
首先修正你代码的拼写错误:你写的std::unordred_set是笔误,正确写法为std::unordered_set。
完整实现代码如下:
#include <boost/multi_index_container.hpp> #include <boost/multi_index/hashed_index.hpp> #include <boost/multi_index/member.hpp> #include <unordered_set> #include <string> struct Student { int Id; std::unordered_set<std::string> Clubs; }; // 自定义多值键提取器,将学生的所有俱乐部名称作为该元素的多个索引键 struct ClubsExtractor { using result_type = std::string; template<typename Func> void operator()(const Student& s, Func func) const { for (const auto& club : s.Clubs) { func(club); } } }; // 定义MultiIndex容器的索引结构 namespace bmi = boost::multi_index; using StudentContainer = bmi::multi_index_container< Student, bmi::indexed_by< // 第一个索引:按Id的唯一哈希索引 bmi::hashed_unique<bmi::member<Student, int, &Student::Id>>, // 第二个索引:按俱乐部名称的非唯一哈希索引,使用自定义提取器 bmi::hashed_non_unique<ClubsExtractor> > >;
使用示例
#include <iostream> int main() { StudentContainer students; // 插入测试数据:学生1同时加入Technology和Movie两个俱乐部 students.insert({1, {"Technology", "Movie"}}); // 调用俱乐部索引进行查询 const auto& club_index = students.get<1>(); // 搜索Technology俱乐部的学生 auto [it, end] = club_index.equal_range("Technology"); for (; it != end; ++it) { std::cout << "Technology club found student id: " << it->Id << std::endl; } // 搜索Movie俱乐部的学生,可检索到同一条学生记录 auto [it2, end2] = club_index.equal_range("Movie"); for (; it2 != end2; ++it2) { std::cout << "Movie club found student id: " << it2->Id << std::endl; } return 0; }
注意事项
- 如果需要修改某个学生的Clubs集合,必须调用容器的
modify方法更新索引,否则会出现索引和实际数据不一致的问题 - 多值键提取器的性能和单个学生加入的俱乐部数量正相关,常规场景下俱乐部数量有限,性能完全满足需求
内容的提问来源于stack exchange,提问作者Ben
相关产品推荐
相关产品推荐

