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

递归函数中如何在template上使用operator[]?嵌套vector实现疑问

问题描述

我想要编写代码遍历未知深度的嵌套vector,检查目标索引是否在vector范围内;若不在,则添加空的嵌套vector(同样为未知深度)直至索引可达。

例如,类似{ { { "a" }, { "b" } }, { { "c" } } }的嵌套vector,其数据位于索引[0,0,0]、[0,0,1]和[0,1,0]。若尝试访问索引[0,1,1]并将其设为"d",函数需将vector扩展为{ { { "a"}, { "b" } }, { { "c" }, { "d" } } }。

我计划用template实现该功能,代码如下(为简化未实现赋值逻辑):

template<typename T>
void checkVector(T&& vec, vector<int> indexes, int counter = 0) {
    // Base Case
    if (counter > int(indexes.size()) - 1) 
    {
        return;
    }

    // Add to vector
    while (indexes[counter] > int(vec.size()) - 1)
    {
        vec.push_back({ {} });
    }

    // Recursive
    checkVector(vec[indexes[counter]], indexes, counter++);
}

但递归部分无法运行,因为在template上使用operator[]会改变类型,导致编译失败。我有两个问题:

  1. 如何在template中进行索引,并告知编译器该对象同样具备template T的属性?
  2. 这种实现方式是否可行?

解决方案

问题1的解决思路

你需要区分嵌套vector的中间层和最底层的元素类型,不能用单一模板T处理所有情况。可以通过模板重载实现类型区分:

  • 第一个重载专门处理vector<U>类型(U可以是另一个vector或最终元素类型),负责索引检查、动态扩展和递归调用;
  • 第二个重载匹配所有非vector类型,作为递归终止条件。

修改后的代码示例:

#include <vector>
#include <string>

// 处理中间层:vector类型
template<typename U>
void checkVector(std::vector<U>& vec, const std::vector<int>& indexes, int counter = 0) {
    // 遍历完所有索引,终止递归
    if (counter >= indexes.size()) {
        return;
    }

    // 扩展vector直到当前索引可达
    while (indexes[counter] >= static_cast<int>(vec.size())) {
        vec.emplace_back(); // 直接构造空的U类型对象(U是vector时即为空vector)
    }

    // 递归处理下一层,用counter+1避免post-increment的逻辑错误
    checkVector(vec[indexes[counter]], indexes, counter + 1);
}

// 处理最底层:非vector类型(终止递归)
template<typename T>
void checkVector(T&, const std::vector<int>&, int) {
    // 已到叶子节点,无需操作
}

核心要点:

  • 用vector<U>&作为参数,确保编译器只对vector类型执行索引和扩展操作;
  • 非vector类型的重载自动终止递归,避免类型推断错误;
  • 将indexes改为const引用减少拷贝,用counter+1替代counter++,避免传递自增前的旧值导致逻辑错误。

问题2:实现方式是否可行

你的核心思路(递归遍历+动态扩展vector)是完全可行的,但需要修正原代码中的几个关键问题:

  1. counter++的逻辑错误:post-increment会先传递旧值再自增,导致递归时重复处理同一层,必须改为counter+1;
  2. 模板类型的区分:必须明确区分中间vector层和最终元素层,否则编译器无法正确推断递归类型;
  3. 边界条件优化:原代码中counter > int(indexes.size()) -1可以简化为counter >= indexes.size(),逻辑更直观;
  4. 对象构造效率:用emplace_back()替代push_back({}),直接构造对象而非拷贝临时对象,性能更优。

如果需要添加赋值逻辑,可以调整代码在到达目标索引位置时执行赋值:

template<typename U>
void checkAndAssign(std::vector<U>& vec, const std::vector<int>& indexes, const U& value, int counter = 0) {
    // 到达最后一个索引,执行赋值
    if (counter == indexes.size() - 1) {
        while (indexes[counter] >= static_cast<int>(vec.size())) {
            vec.emplace_back();
        }
        vec[indexes[counter]] = value;
        return;
    }

    // 扩展当前层vector
    while (indexes[counter] >= static_cast<int>(vec.size())) {
        vec.emplace_back();
    }

    // 递归处理下一层
    checkAndAssign(vec[indexes[counter]], indexes, value, counter + 1);
}

调用示例:checkAndAssign(nested_vec, {0,1,1}, std::string("d")),即可完成你示例中的赋值与扩展操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 11:35:35