我在 gtest 源文件中看到这段代码。此代码段用于生成一个模板,其模板变量是一个整数序列。谁能解释一下这是如何工作的?
template <size_t... Is> struct int_pack { typedef int_pack type; };
template <class Pack, size_t I>
struct append;
template <size_t... Is, size_t I>
struct append<int_pack<Is...>, I> : int_pack<Is..., I> {};
template <size_t C>
struct make_int_pack : append<typename make_int_pack<C - 1>::type, C - 1> {};
template <> struct make_int_pack<0> : int_pack<> {};
我们可以使用make_int_pack<5>()
生成一个类实例 ( int_pack<0,1,2,3,4>()
),它进一步用于提取 0,1,2,3,4 来做某事。
最佳答案
构造是通过递归替换完成的:
make_int_pack<5>
源自 append<typename make_int_pack<5-1>::type,5-1>
.
但是make_int_pack<5-1>::type
是make_int_pack<4>::type
.
但是make_int_pack<4>::type
是来自 append<typename make_int_pack<4-1>::type,4-1>
的定义, 等等。
所以 make_int_pack<5>
源自
append<append<append<append<append<int_pack<>,0>,1>,2>,3>,4>
,源自 int_pack<0,1,2,3,4>
.
使用这个int_pack
我们必须做一些类似模式匹配 (c++11) 的事情。
template<class T>struct test{};
template<size_t ... Is>
struct test<int_pack<Is...>>{
// use template parameter pack
};
然后我们可以使用 test<make_int_pack<5>>
的静态成员作为某些编译时编译或复杂类型构造的结果。
另一种可能的方式是让
template<size_t... Is>
size_t test_fun(int_pack<Is...>);
,它会被称为 test_fun(make_int_pack<5>());
编辑:
I'm wondering why there's two append struct, what's the difference between them?
你希望能够写出 append<int_pack<0,1,2,3>,42>
.为此append
必须采用两个模板参数。那是你的第一个声明。
template<class T,size_t i> struct append{};
但实际上你不需要类型 int_pack<0,1,2,3>
但是使用了模板参数包。在 C++ 中,我们有部分模板特化。如果类型 T
碰巧是一个int_pack
我们使用特殊(第二)声明。通过这种方式,我们可以匹配模板类型 T
的模式。并获取使用的模板参数来定义 int_pack
.
template<size_t ... Is,size_t i>
struct append<int_pack<Is...>,i> : int_pack<Is...,i>{};
what's the meaning of append,0> ?
这会属于第二种情况。我们有一个空的模板参数包,因为括号是空的 int_pack<>
.所以我们来自 int_pack<0>
因此我们的 append<int_pack<>,0>::type
是int_pack<0>
.
总结一下: 查看模板参数包和部分模板特化。 使用类型时,基本上只是替换表达式。
关于c++ - 如何使用模板生成整数序列在这里工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58602246/