我有这段代码可以生成1到10的编译时数组
template <int... Is> // when called below, Is will be 0 - N
constexpr std::array<int, sizeof...(Is)>
make_inc_array_impl(std::integer_sequence<int, Is...>) {
return {{(Is + 1)...}}; // +1 to start at one instead of [0, 1, ...]
}
template <std::size_t N>
constexpr std::array<int, N> make_inc_array() {
return make_inc_array_impl(std::make_integer_sequence<int, N>{});
}
constexpr auto a = make_inc_array<10>(); // [1, 2, ..., 10]
int main() {
for(int itr = 0; itr < 10; ++itr)
printf("%d ", a[itr]);
}
嗯,我对元编程的工作方式有一些经验和知识。但是我仍然不知道这个惊人的例子是如何工作的。
从make_inc_array_impl()
中,我看到它返回(Is+1)...
,那么由于[11, 10, 9, 8, 7, ... 2]
的值从Is
开始,结果应该是10
吗?
可变参数模板功能make_integer_sequence(parameter pack)
如何展开/展开std::integer_sequence<int, Is...>
?在正常的元编程中,模板推导从N
到N-1
,直到1
递归地工作。但是,为什么它会从1
到N
?
您能帮您解释一下背后的原理吗?
答案 0 :(得分:3)
对make_inc_array<10>()
的调用返回make_inc_array_impl(std::make_integer_sequence<int, 10>{})
。 std::make_integer_sequence
是别名模板。特别是,它被实现为std::make_integer_sequence<int, 10>
是类型std::integer_sequence<int, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9>
的别名。因此,当使用这种类型的参数调用make_inc_array_impl
时,为了使参数类型Is...
等于参数类型,推论0 1 2 3 4 5 6 7 8 9
到std::integer_sequence<int, Is...>
。最后,此包在make_inc_array_impl
的正文中进行了扩展。包扩展按顺序发生,因此变成0 + 1
,1 + 1
,...,9 + 1
。
其中最棘手的部分是std::make_integer_sequence
。如何将其扩展为具有所需的实际连续整数的std::integer_sequence
专长?好吧,这已插入到标准库中,因此您不必自己记住如何做,但是如果您想查看答案,请看here。
通常需要一个辅助函数,该辅助函数将以std::make_integer_sequence<int, N>{}
的结果进行调用,以便有一个位置可以将各个整数放在包{{1 }}。现在,您已经知道了这一技巧,您将开始看到许多可以使用它的地方。