为什么这种可变模板参数的替换失败了?(在固定参数之前打包)

Why is this substitution of variadic template parameter failing ? (pack before fixed arguments)

本文关键字:参数 失败 为什么 替换      更新时间:2023-10-16

这里有一个触发编译错误的最小示例:

#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

此处的参数推导失败:

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);
}

这是有效的:

template <class F, class... Args>
void post_forwarder(F f, Args&&... aArgs) {
    f(std::forward<Args>(aArgs)..., 5);
}

现场演示

编辑:重写答案:

形式Args..., int不允许推导Args...