如何在递归函数中的模板上使用 operator[]

How to use operator[] on a template in a recursive function

提问人:joysterling 提问时间:4/26/2023 最后编辑:joysterling 更新时间:5/1/2023 访问量:64

问:

我正在尝试编写一些代码,这些代码将遍历某个未知深度的嵌套向量,并检查我们想要访问的索引是否在向量内;如果没有,我想添加空嵌套向量(同样,具有未知深度),直到我们到达这些索引。

例如,嵌套向量 like 在索引 [0, 0, 0], [0, 0, 1] 和 [0, 1, 0] 处具有数据。如果我们尝试访问索引 [0, 1, 1] 处的向量并将其设置为等于 “d”,则该函数会将向量扩展为 。{ { { "a" }, { "b" } }, { { "c" } } }{ { { "a"}, { "b" } }, { { "c" }, { "d" } } }

我的想法是使用模板来实现这一点,就像这样(底部代码没有设置值,只是为了保持简单):

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++);
}

但是,递归部分不起作用,因为在模板上使用运算符 [] 会更改类型,因此它不会编译。所以我有两个问题:

  1. 如何索引到模板中并告诉编译器它也具有与模板 T 相同的属性?
  2. 这甚至是正确的方法吗?

谢谢大家!如果我对任何事情不清楚,请告诉我。

C++ 模板 递归 运算符重载

评论

0赞 Remy Lebeau 4/26/2023
我会改为,然后如果需要,提供一个重载来处理这种情况 when is not a ie when 恰好返回一个非嵌套的非向量元素。T&&vector<T>&checkVector()Tvectorvec[indexes[counter]]
0赞 joysterling 5/1/2023
谢谢雷米!这很好用。我附上此代码作为原始问题的答案。

答:

0赞 Jarod42 4/26/2023 #1

使用常规时,所有分支都应该在模板中有效。if

您可以使用(或重载)来具有不同的路径。 但条件应该是 a(所以不能依赖于参数的值)。if constexprconstexpr

例如,您可以执行以下操作:

template<typename T, typename U>
void setVectorAt(std::vector<T>& vec,
                 std::vector<std::size_t> indexes,
                 const U& value,
                 std::size_t counter = 0)
{
    // Add to vector
    vec.resize(std::max(1 + indexes[counter], vec.size()));
    if constexpr (std::is_assignable_v<T, U>) {
        vec[indexes[counter]] = value;
    } else {
        setVectorAt(vec[indexes[counter]], indexes, value, counter + 1);
    }
}

演示

0赞 joysterling 5/1/2023 #2

对于稍后查看此线程的任何人,我继续写下了 Remy 关于如何处理递归向量的建议:

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

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

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

template<typename T>
void checkVector(T&& t, vector<int> indexes, int counter) {
    return;
}