【发布时间】:2016-08-05 09:17:27
【问题描述】:
来自用户 Faheem Mitha 的以下代码基于用户 Johannes Schaub - litb 在此 SO 中的回答。这段代码完美地完成了我所寻求的,即将tuple 转换为参数包,但我对这段代码的理解不够好,因此我想我会创建一个新的讨论,可能有助于像我这样的模板元编程新手。所以,请原谅重复的帖子。
现在进入代码
#include <tuple>
#include <iostream>
using std::cout;
using std::endl;
template<int ...> struct seq {};
template<int N, int ...S> struct gens : gens<N - 1, N - 1, S...> { };
template<int ...S> struct gens<0, S...>{ typedef seq<S...> type; };
double foo(int x, float y, double z)
{
return x + y + z;
}
template <typename ...Args>
struct save_it_for_later
{
std::tuple<Args...> params;
double(*func)(Args...);
double delayed_dispatch()
{
return callFunc(typename gens<sizeof...(Args)>::type()); // Item #1
}
template<int ...S>
double callFunc(seq<S...>)
{
return func(std::get<S>(params) ...);
}
};
int main(void)
{
std::tuple<int, float, double> t = std::make_tuple(1, (float)1.2, 5);
save_it_for_later<int, float, double> saved = { t, foo };
cout << saved.delayed_dispatch() << endl;
return 0;
}
我完全被上面的第 1 项弄糊涂了:
-
typename在那条线上有什么用途? - 我知道
gens<sizeof...(Args)>::type()将扩展为gens<3>::type(),但这似乎与template<int N, int ...S> struct gens : gens<N - 1, N - 1, S...> { };和template<int ...S> struct gens<0, S...>都不匹配。我显然没有抓住重点,如果有人能解释这里发生的事情,我会很高兴。
我知道callFunc 以callFunc(seq<0,1,2>) 这种形式调用,并且此方法本身的返回语句扩展为return func(std::get<0>(params), std::get<1>(params), std::get<2>(params),这就是使该方案有效的原因,但我无法确定seq<0,1,2> 类型如何已生成。
注意:不能使用std::index_sequence_for,我的编译器不支持 C++14 功能。
PS:这种技术可以归类为模板元编程吗?
【问题讨论】:
-
1) 通知编译器
gens<sizeof...(Args)>::type是一种类型,而不是成员函数。 2) 参数包可以为空。 -
gens<3>确实与template<int N, int ...S> struct gens匹配,N==3和S是一个空包。 -
基本上,
seq是std::index_sequence和gens是std::make_index_sequence -
@T.C.为什么编译器需要那个提示?我的意思是,除了
seq<S...>()构造函数调用之外,它怎么可能混淆gens<sizeof...(Args)>::type()表达式? -
当你可以使用 C++17 时,它应该从
<tuple>折叠到std::apply()。
标签: c++ templates c++11 variadic-templates