make_index_sequence是如何工作的?

3

我在理解这段代码的时候遇到了麻烦。我知道它生成了一个数字序列,来源于https://dev59.com/G3M_5IYBdhLWcg3w2XLw#24481400。但我无法从中得出逻辑,我需要一些指导来帮助我走过这段路程。尤其是为什么要用N-1, N-1?

template <size_t ...I>
struct index_sequence {};

template <size_t N, size_t ...I>
struct make_index_sequence : public make_index_sequence<N - 1, N - 1, I...> {};

template <size_t ...I>
struct make_index_sequence<0, I...> : public index_sequence<I...> {};

make_index_sequence<sizeof...(T)>()对于do_foo_helper有什么影响?它似乎只是将一个没有名称的函数传递给函数,并且还需要一些帮助。

template<typename ...T, size_t ...I>
/* ... */ do_foo_helper(std::tuple<T...> &ts, index_sequence<I...>) {
    std::tie(foo(std::get<I>(ts)) ...);
}

template <typename ...T>
/* ... */ do_foo(std::tuple<T...> &ts) {
    return do_foo_helper(ts, make_index_sequence<sizeof...(T)>());
}
1个回答

5

让我们来玩编译器,为模板参数替换值。

当遇到像std::make_index_sequence<3>这样的类型时,它会查看模板及其特化,并匹配到

template <3>
struct make_index_sequence : public make_index_sequence<2, 2> {};
make_index_sequence<3>的基类是make_index_sequence的另一个实例,因此我们使用新参数重复这个过程。
template <2, 2>
struct make_index_sequence : public make_index_sequence<1, 1, 2> {};

And again

template <1, 1, 2>
struct make_index_sequence : public make_index_sequence<0, 0, 1, 2> {};

现在我们进入专业领域。
template <0, 1, 2>
struct make_index_sequence<0, 0, 1, 2> : public index_sequence<0, 1, 2> {};

现在我们有一个继承(间接)自index_sequence<0, 1, 2>的类型,因此模板函数可以将参数包绑定到0, 1, 2以匹配传递的参数。 sizeof...(T)只是用于计算参数包T的大小的运算符,因此我们有以下示例:
template <int, bool, char>
/* ... */ do_foo(std::tuple<int, bool, char> & ts)
{
    return do_foo_helper(ts, make_index_sequence<3>());
}

哪些调用

template <int, bool, char, 0, 1, 2>
/* ... */ do_foo_helper(std::tuple<int, bool, char> & ts, std::index_sequence<0, 1, 2>)
{
    std::tie(foo(std::get<0>(ts)), foo(std::get<1>(ts)), foo(std::get<2>(ts)));
}

也就是说,我们只需要第二个参数的类型,而不需要它的值(std::index_sequence<0, 1, 2> 只有一种值,它没有数据成员)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接