Don*_*alo 2 c++ templates variadic-templates c++17
我正在看这个关于auto in template参数的优点的答案.
请考虑以下异构列表:
template <auto ... vs> struct HeterogenousValueList {};
using MyList1 = HeterogenousValueList<42, 'X', 13u>;
Run Code Online (Sandbox Code Playgroud)
现在我已经声明了一个名为的类型MyList1.如何从此类型中提取存储的数据(即42,'x'或13u)?
小智 7
要从模板参数包中提取数据,我们通常在模板中进行模式匹配.
首先,我们创建一个类模板,At但没有内容.它的模板参数应该是一个索引,一个实例HeterogenousValueList.此类模板将像函数一样用于访问列表中的信息.
template <int Index, class ValueList>
struct At;
Run Code Online (Sandbox Code Playgroud)
接下来,我们创建一个专业化At.这是使用模式匹配的地方.通过模式匹配,列表的第一个元素将成为u.列表的其余部分将是vs.如果是索引0,u则可以通过静态成员访问value.请注意,这vs可以是一个空列表,因此这也涵盖了u作为列表最后一个的情况.
template <auto u, auto... vs>
struct At<0, HeterogenousValueList<u, vs...>>
{
static constexpr auto value = u;
};
Run Code Online (Sandbox Code Playgroud)
如果指数不为0怎么办?我们移动列表并将索引递减1,然后再将它们传递给它们At.换句话说,这是一个模板递归.
template <int Index, auto u, auto... vs>
struct At<Index, HeterogenousValueList<u, vs...>>
{
static constexpr auto value = At<Index - 1, HeterogenousValueList<vs...>>::value;
};
Run Code Online (Sandbox Code Playgroud)
现在,我们可以尝试使用它:https://godbolt.org/g/51dpH8
int main()
{
volatile auto value0 = At<0, MyList1>::value;
volatile auto value1 = At<1, MyList1>::value;
volatile auto value2 = At<2, MyList1>::value;
// volatile auto value3 = At<-1, MyList1>::value;
// volatile auto value4 = At<3, MyList1>::value;
}
Run Code Online (Sandbox Code Playgroud)
我使用volatile变量,以便编译器不会优化效果,您可以在程序集列表中看到效果.
还有一件好事:编译器检查绑定!由于运行时效率原因,我们通常没有对运行时数组进行绑定检查.但这是一个编译时列表.编译器可以为我们做!
实际上,有一个更简单的实现.这一次,我们在函数模板中使用constexpr-if.但模式匹配和模板递归的想法保持不变.
template <int Index, auto u, auto... vs>
auto at(HeterogenousValueList<u, vs...>)
{
if constexpr (Index == 0)
return u;
else
return at<Index - 1>(HeterogenousValueList<vs...>{});
}
Run Code Online (Sandbox Code Playgroud)
而这一次,当我们使用它时,我们需要实例MyList1化为一个对象.
int main()
{
volatile auto value0 = at<0>(MyList1{});
volatile auto value1 = at<1>(MyList1{});
volatile auto value2 = at<2>(MyList1{});
// volatile auto value3 = at<-1, MyList1>::value;
// volatile auto value4 = at<3, MyList1>::value;
}
Run Code Online (Sandbox Code Playgroud)