【问题标题】:C++ parameter pack expansionC++参数包扩展
【发布时间】:2018-06-12 03:30:26
【问题描述】:

下面的代码不能编译(见代码下面的错误)。你能解释一下为什么吗?

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:错误:表达式包含未扩展的参数包 '精氨酸'

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

【问题讨论】:

  • 请定义“不工作”。不会编译?不正确的行为(例如崩溃)?
  • 请编辑您的问题以解释这段代码应该做什么,实际发生了什么,抛出的错误等。否则,这里的人将不得不检查您的代码,弄清楚它,调试它等等。正如所写,不幸的是,这与“不清楚你在问什么”或“为什么我的代码不起作用”是题外话。
  • f(std::forward&lt;Arg&gt;(arg...)); => (f(std::forward&lt;Arg&gt;(arg)) , ...); 如果你使用的是c++17
  • @super 值得回答!这是一个很好的答案,所以如果你回答它会很酷。如果你不这样做,我会自己做:D
  • 顺便说一句,试图关闭这个问题的人可能会考虑撤回他们的投票。我认为这个问题不再不清楚了

标签: c++ templates


【解决方案1】:

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

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)), ...);

【讨论】:

    【解决方案2】:

    扩展参数包适用于需要逗号分隔列表的上下文。

    也就是你的代码:

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

    它试图扩展为:

    f( "Aa", 3, 4 );
    

    而且您提供的 lambda 不支持这样的调用。

    要将参数包扩展为多个函数调用,请使用递归函数。

    template <class F>
    void for_each_argument(F f)
    {
        // (No args)
    }
    
    template <class F, class FirstArg, class... MoreArgs>
    void for_each_argument(F f, FirstArg&& first_arg, MoreArgs&&... more_args)
    {
        f( std::forward<FirstArg>(first_arg) );
        for_each_argument( f, std::forward<MoreArgs>(more_args)... );
    }
    

    【讨论】:

    • 嗯。 R Sahu 正在写一些非常相似的东西并删除了他们的答案。我不知道为什么。
    • @SergeyA 它是。我确信这个问题中的代码至少是 C++11,所以我确信这个答案会起作用。
    • @DrewDormann Variadics 是 C++11,所以是的,这段代码可以工作。它只是过时的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-06
    • 1970-01-01
    • 2023-03-10
    • 1970-01-01
    • 2023-03-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多