You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过大括号初始化递归式std::unordered_map及树形结构Tree

问题描述

需要实现一个树形结构类型,支持两种方式的大括号初始化:

Tree t1 = 1;  // 单个值初始化
Tree t2 = {{"a",t1},{"b",{{"x",2},{"y",4}}},{"c",5}};  // 嵌套键值对初始化

最初尝试继承std::unordered_map,并用unique_ptr包装递归的Tree对象,但无法正确编写初始化列表构造函数,代码如下:

// 原错误实现
using std;
struct Tree : unordered_map<string, unique_ptr<Tree>>{
    int simple;

    Tree() = default;
    Tree(unsigned s): simple{s}{};
    Tree(const initializer_list<pair<string, unique_ptr<Tree>>> & il): simple{s} {
        // 编译失败,且指针类型无法匹配用户期望的初始化写法
    }
};

另有一个基于vector的可行实现作为参考:

struct TreeV : vector<pair<string, TreeV>>{
    TreeV(const vector<pair<string, TreeV>> & v) : vector<pair<string, TreeV>>(v){};
};
vector<pair<string, TreeV>> t3 = {{"a",t1},{"b",{{"x",2},{"y",4}}},{"c",5}};

需要解决的核心问题:如何让继承自std::unordered_map的递归Tree类型支持用户期望的嵌套大括号初始化语法?

解决方案

核心思路是调整构造函数的参数类型,让其匹配用户的初始化写法,同时在内部处理Tree对象到unique_ptr<Tree>的转换。具体实现如下:

#include <unordered_map>
#include <string>
#include <memory>

using namespace std;

struct Tree : unordered_map<string, unique_ptr<Tree>> {
    int simple;

    // 默认构造函数,初始化simple为0
    Tree() : simple(0) {}
    // 单个int值初始化
    Tree(int s) : simple(s) {}
    // 接受嵌套大括号的初始化列表构造函数
    Tree(initializer_list<pair<string, Tree>> il) : simple(0) {
        for (auto&& entry : il) {
            // 将传入的Tree对象转移为unique_ptr,插入到map中
            emplace(entry.first, make_unique<Tree>(move(entry.second)));
        }
    }

    // 支持赋值运算符接收初始化列表
    Tree& operator=(initializer_list<pair<string, Tree>> il) {
        clear();
        simple = 0;
        for (auto&& entry : il) {
            emplace(entry.first, make_unique<Tree>(move(entry.second)));
        }
        return *this;
    }
};

关键说明

  1. 构造函数参数匹配:将初始化列表参数改为initializer_list<pair<string, Tree>>,完全匹配用户{"key", Tree对象}的写法,避免了直接使用unique_ptr带来的类型不兼容问题。
  2. 内部指针转换:在构造函数中,通过std::make_unique和std::move将传入的Tree对象转移为unique_ptr<Tree>,既保证了内存安全,又符合unordered_map的存储需求。
  3. 嵌套初始化支持:嵌套的{{"x",2},{"y",4}}会自动调用Tree的初始化列表构造函数生成一个子Tree对象,再被外层构造函数处理为指针插入到父节点中,完美支持递归嵌套语法。
  4. 赋值运算符补充:重载赋值运算符,让Tree对象可以直接被初始化列表赋值,进一步贴合用户的使用习惯。

验证代码

使用用户期望的写法测试:

int main() {
    Tree t1 = 1;
    Tree t2 = {{"a", t1}, {"b", {{"x", 2}, {"y", 4}}}, {"c", 5}};
    
    // 验证结构:t2["a"]指向t1的副本,t2["b"]包含两个子节点,t2["c"]指向值为5的Tree
    return 0;
}

内容的提问来源于stack exchange,提问作者danculo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 09:18:35