首页 > 解决方案 > C++参数包扩展

问题描述

下面的代码无法编译(请参阅代码下方的错误)。你能解释一下为什么吗?

template <class F, class... Arg>
void for_each_argument(F f, Arg&&... arg)
{
   f(std::forward<Arg>(arg...));
}
int main()
{
   for_each_argument(
     [](const auto& a){std::cout<< a;}, "Aa", 3, 4);
   return 0;
}

这是一条错误消息:

7:4:错误:表达式包含未扩展的参数包“Arg”

f(std::forward(arg...));

标签: c++templates

解决方案


您的代码中有几个问题。首先,您的原始行

f(std::forward<Arg>(arg...));

根本不是正确的语法 - 您正在扩展而没有在模板中arg正确扩展。Arg现在,您至少可以通过以下方式解决此问题

f(std::forward<Arg>(arg)...);

这会更好,但仍然是错误的——你会用 3 个参数调用你的 lambda 一次,而它只接受一个参数——相反,你想用一个参数调用 lambda 3 次。

有几种方法可以做到这一点。首先,也是最不推荐的,是递归调用函数,正如其他答案所暗示的那样。这会提示难看的语法,也增加了递归模板实例化的编译器负担。更好的解决方案是使用数组技巧扩展参数,例如(为简单起见忽略前向):

auto lam = [&f](const auto& a) { f(a); return true;}
bool arr[] = { lam(std::forward<ARG>(arg))... };
(void)arr;

在 C++ 17 中,您可以使用折叠表达式来实现更简洁的语法:

(f(std::forward<ARG>(arg)), ...);

推荐阅读