为什么这个可变参数模板参数的替换失败了? (在固定参数之前打包)
Why is this substitution of variadic template parameter failing ? (pack before fixed arguments)
这是触发编译错误的最小示例:
#include <utility>
void foo(int, double, int)
{}
template <class... Args>
void post_forwarder(void(*fun)(Args..., int), Args&&... aArgs)
{
fun(std::forward<Args>(aArgs)..., 5);
}
int main()
{
post_forwarder(foo, 6, 6.1); // Compilation error on instantiation
return 0;
}
我怀疑这个问题与可变参数模板参数在固定 int 参数之前在函数类型中扩展有关,但如果是这样,我找不到很好的理由。
Clang 3.6报错为:
error: no matching function for call to 'post_forwarder'
note: candidate template ignored: failed template argument deduction
编辑:重写答案:
形式 Args..., int
不允许推导 Args...
。
这个有效:
template <class F, class... Args>
void post_forwarder(F f, Args&&... aArgs) {
f(std::forward<Args>(aArgs)..., 5);
}
此处推导失败:
template <class... Args>
void post_forwarder(void(*fun)(Args..., int), Args&&... aArgs)
// ^^^^^^^
参数包必须位于末尾才能推导的一般规则。通常的解决方案是将其包装在不可推导的上下文中,这样推导就不会被尝试:
template <typename T>
struct identity {
using type = T;
};
template <class... Args>
void post_forwarder(void(*fun)(typename identity<Args>::type..., int), Args&&... aArgs)
{
fun(std::forward<Args>(aArgs)..., 5);
}
这是触发编译错误的最小示例:
#include <utility>
void foo(int, double, int)
{}
template <class... Args>
void post_forwarder(void(*fun)(Args..., int), Args&&... aArgs)
{
fun(std::forward<Args>(aArgs)..., 5);
}
int main()
{
post_forwarder(foo, 6, 6.1); // Compilation error on instantiation
return 0;
}
我怀疑这个问题与可变参数模板参数在固定 int 参数之前在函数类型中扩展有关,但如果是这样,我找不到很好的理由。
Clang 3.6报错为:
error: no matching function for call to 'post_forwarder'
note: candidate template ignored: failed template argument deduction
编辑:重写答案:
形式 Args..., int
不允许推导 Args...
。
这个有效:
template <class F, class... Args>
void post_forwarder(F f, Args&&... aArgs) {
f(std::forward<Args>(aArgs)..., 5);
}
此处推导失败:
template <class... Args>
void post_forwarder(void(*fun)(Args..., int), Args&&... aArgs)
// ^^^^^^^
参数包必须位于末尾才能推导的一般规则。通常的解决方案是将其包装在不可推导的上下文中,这样推导就不会被尝试:
template <typename T>
struct identity {
using type = T;
};
template <class... Args>
void post_forwarder(void(*fun)(typename identity<Args>::type..., int), Args&&... aArgs)
{
fun(std::forward<Args>(aArgs)..., 5);
}