所以我遇到了在元组中存储可变参数的问题,以便稍后用这些来调用函数。我找到了Kerrek SB的答案,这样做非常好,但我不明白它到底是做什么的。这是代码:
// implementation details, users never invoke these directly
namespace detail
{
template <typename F, typename Tuple, bool Done, int Total, int... N>
struct call_impl
{
static void call(F f, Tuple && t)
{
call_impl<F, Tuple, Total == 1 + sizeof...(N), Total, N..., sizeof...(N)>::call(f, std::forward<Tuple>(t));
}
};
template <typename F, typename Tuple, int Total, int... N>
struct call_impl<F, Tuple, true, Total, N...>
{
static void call(F f, Tuple && t)
{
f(std::get<N>(std::forward<Tuple>(t))...);
}
};
}
// user invokes this
template <typename F, typename Tuple>
void call(F f, Tuple && t)
{
typedef typename std::decay<Tuple>::type ttype;
detail::call_impl<F, Tuple, 0 == std::tuple_size<ttype>::value, std::tuple_size<ttype>::value>::call(f, std::forward<Tuple>(t));
}
基本上,困扰我的部分如下:
template <typename F, typename Tuple, bool Done, int Total, int... N>
struct call_impl
{
static void call(F f, Tuple && t)
{
call_impl<F, Tuple, Total == 1 + sizeof...(N), Total, N..., sizeof...(N)>::call(f, std::forward<Tuple>(t));
}
};
我理解N...
和sizeof...(N)
存在某种TMP递归,它会将Done
设置为true
的部分特化停止,这发生在条件Total == 1 + sizeof...(N)
已经过验证。
我无法理解的是N...
来自哪里。我无法看到它的起源......
有人可以解释这个实现是如何工作的吗? (如果那不是SO的话题。)
答案 0 :(得分:2)
第一次调用:
typedef typename std::decay<Tuple>::type ttype;
detail::call_impl<
F, Tuple, 0 == std::tuple_size<ttype>::value, std::tuple_size<ttype>::value
>::call(f, std::forward<Tuple>(t));
请注意,他们将4个参数传递给call_impl
。
<typename F, typename Tuple, bool Done, int Total, int... N>
struct call_impl
在这里你可以看到它需要4个参数,然后是int...
。 int...
表示“零或更多int
s”。所以它从零int
开始。
但除非Done
为空,否则ttype
为false。
如果Done
为false,则使用基本实例:
call_impl<F, Tuple, Total == 1 + sizeof...(N), Total, N..., sizeof...(N)>::call(f, std::forward<Tuple>(t));
最初N...
为空,因此sizeof...(N)
为0
。这最终以
call_impl<F, Tuple, Total == 1 + 0, Total, 0>::call(f, std::forward<Tuple>(t));
使用N...
填充0
。如果Done
,则Total==1
设置为true。如果没有,我们会递归,最后将N...
设置为0,1
,重复到Done
。一旦Done
成立,我们就会N...
填充0, 1, 2,
...最多Total-1
。
Done
为true会导致调用此特化:
template <typename F, typename Tuple, int Total, int... N>
struct call_impl<F, Tuple, true, Total, N...>
进行通话。
现在,这是一种奇怪而又笨拙的方法,可以使用Total
构建基于{{1}}的序列,然后将包含该序列的类型作为参数传递给函数,并推导出序列。类型。但上述技术有效。