C++中创建嵌套std::map的简易接口及扩展实现问询
动态嵌套容器的实现方案
首先明确:编译时确定层数可以用模板元编程,但你的需求是运行时解析文件后确定层数,C++作为静态类型语言,静态嵌套的std::map(比如std::map<int, std::map<...>>)无法满足——因为类型结构在编译时就已固定。因此需要用动态类型封装来实现。
一、纯嵌套map的动态实现
无需宏或模板元编程,用递归变体类型模拟动态嵌套结构即可,C++17及以上支持的std::variant是理想选择:
#include <map> #include <variant> #include <stdexcept> // 前向声明递归结构 struct NestedMap; // 定义递归变体:要么是计数int,要么是map<int, NestedMap> using NestedValue = std::variant<int, std::map<int, NestedMap>>; struct NestedMap { NestedValue value; // 构造函数:默认创建叶子计数节点,传入false则创建空map节点 NestedMap(bool is_leaf = true) { if (is_leaf) value = 0; else value = std::map<int, NestedMap>(); } // 访问嵌套map的key NestedMap& operator[](int key) { if (std::holds_alternative<int>(value)) throw std::runtime_error("无法在叶子节点上访问map"); return std::get<std::map<int, NestedMap>>(value)[key]; } // 获取计数 int& count() { if (!std::holds_alternative<int>(value)) throw std::runtime_error("非叶子节点无计数"); return std::get<int>(value); } }; // 创建指定层数的嵌套map结构 NestedMap CreateNestedMaps(int depth) { if (depth <= 0) throw std::invalid_argument("层数必须大于0"); if (depth == 1) return NestedMap(true); return NestedMap(false); // 非叶子节点,后续可动态添加key }
使用示例:
int main() { auto map4 = CreateNestedMaps(4); map4[1][2][3][4].count()++; // 四层嵌套计数 std::cout << map4[1][2][3][4].count() << std::endl; // 输出1 return 0; }
二、混合map与vector的动态实现
扩展变体类型,加入std::vector即可支持混合嵌套:
#include <map> #include <vector> #include <variant> #include <stdexcept> struct NestedContainer; // 扩展变体:支持计数int、map<int, NestedContainer>、vector<NestedContainer> using NestedValue = std::variant<int, std::map<int, NestedContainer>, std::vector<NestedContainer>>; struct NestedContainer { NestedValue value; // 根据类型构造:0=计数,1=map,2=vector NestedContainer(int type = 0) { switch (type) { case 0: value = 0; break; case 1: value = std::map<int, NestedContainer>(); break; case 2: value = std::vector<NestedContainer>(); break; default: throw std::invalid_argument("无效容器类型"); } } // map的key访问 NestedContainer& operator[](int key) { if (!std::holds_alternative<std::map<int, NestedContainer>>(value)) throw std::runtime_error("当前不是map容器"); return std::get<std::map<int, NestedContainer>>(value)[key]; } // vector的索引访问(自动扩容) NestedContainer& operator[](size_t idx) { if (!std::holds_alternative<std::vector<NestedContainer>>(value)) throw std::runtime_error("当前不是vector容器"); auto& vec = std::get<std::vector<NestedContainer>>(value); if (idx >= vec.size()) vec.resize(idx + 1); return vec[idx]; } // 获取计数 int& count() { if (!std::holds_alternative<int>(value)) throw std::runtime_error("非叶子节点无计数"); return std::get<int>(value); } }; // 根据每层类型创建混合结构(types数组最后一位必须是0,代表计数节点) NestedContainer CreateMixedContainers(const std::vector<int>& types) { if (types.empty() || types.back() != 0) throw std::invalid_argument("最后一层必须是计数节点(类型0)"); NestedContainer root(types[0]); NestedContainer* current = &root; for (size_t i = 1; i < types.size(); ++i) { // 根据当前容器类型创建下一层节点 if (std::holds_alternative<std::map<int, NestedContainer>>(current->value)) { current = &(std::get<std::map<int, NestedContainer>>(current->value)[0]); } else if (std::holds_alternative<std::vector<NestedContainer>>(current->value)) { auto& vec = std::get<std::vector<NestedContainer>>(current->value); vec.emplace_back(types[i]); current = &vec.back(); } else { throw std::runtime_error("无法在叶子节点上嵌套"); } // 重置当前节点为指定类型 switch (types[i]) { case 0: current->value = 0; break; case 1: current->value = std::map<int, NestedContainer>(); break; case 2: current->value = std::vector<NestedContainer>(); break; } } return root; }
使用示例:
int main() { // 结构:map -> vector -> map -> 计数 std::vector<int> types = {1, 2, 1, 0}; auto container = CreateMixedContainers(types); container[1][0][2].count() += 5; std::cout << container[1][0][2].count() << std::endl; // 输出5 return 0; }
三、为什么不适合宏或模板元编程?
- 宏:属于预处理器阶段,只能处理编译时已知的层数,完全不支持运行时动态层数。
- 模板元编程:模板在编译期展开,层数必须是编译期常量,无法适配解析文件后才确定的动态层数。
四、简化替代方案:扁平化容器
如果分类键可以组合为单一标识,直接用扁平化的map更简单,比如用std::tuple或std::vector<int>作为key:
// 四层分类用tuple作为key std::map<std::tuple<int, int, int, int>, int> counter; counter[{1,2,3,4}]++; // 直接计数 // 支持动态层数的版本(需自定义vector<int>的哈希) #include <functional> struct VectorHash { size_t operator()(const std::vector<int>& v) const { size_t hash = 0; for (int i : v) hash ^= std::hash<int>()(i) + 0x9e3779b9 + (hash << 6) + (hash >> 2); return hash; } }; std::unordered_map<std::vector<int>, int, VectorHash> dynamic_counter; dynamic_counter[{1,2,3,4}]++;
内容的提问来源于stack exchange,提问作者dexzoyp
相关产品推荐
相关产品推荐

