【问题标题】:Variadic Template lambda expansion可变参数模板 lambda 展开
【发布时间】:2012-04-09 01:19:49
【问题描述】:

我正在尝试在Herb Sutter's Example 之后实现一个委托类。本文中有一个部分复制了几个模板;列表中参数数量的一个模板(示例 7,第 41 - 59 行)1。我正在尝试用可变参数模板替换它。

void operator()() const {
    for_each(begin(l_), end(l_), []( function<F> i) {
            i(); 
    });
}

template<typename... Ts>
    void operator()(Ts... vs) const {
        for_each(begin(l_), end(l_), [&, vs...]( function<F> i) //g++-4.6.1: expected ',' before '...' token; expected identifier before '...' token
        { 
                i(vs...);
        });
    }

我找到了这个answer,但我认为我的问题是 vs 没有扩展。这样做的正确方法是什么?

【问题讨论】:

  • 这不是转发函数的正确用法。您想要的是将您的参数作为(Ts&amp;&amp; ...vs),然后将它们作为i(std::forward(vs)...) 转发给函数。这可能无法解决您的问题,但这就是 C++11 中完美转发的方式。
  • 我可能不明白你的意思,但我不想动议。在这种情况下,副本是正确的。每个回调获取事件参数的副本。在某些情况下,移动语义会起作用,但复制更为通用。对吗?
  • 转发将根据需要移动或复制参数。完美转发背后的理念是它是完美:与您直接调用i 的方式相同。因此,如果i 按值获取其参数并且您传递一个左值,它将复制。如果你传递一个右值,它会移动,这正是如果你直接调用i 会发生什么。如果用户想要进入函数参数,您不能(也不应该)阻止它们。那是他们的事。您只需要担心完美地转发参数,这就是 C++11 的语法。
  • 这非常有帮助。谢谢!

标签: c++ c++11 variadic-templates lambda


【解决方案1】:

我不确定为什么vs 没有扩展,但也许简单的解决方法是按值传递参数作为默认值,并命名需要通过引用传递的已知对象。这样就不需要在捕获列表中进行扩展。就个人而言,如果这是 gcc 中的错误,我不会感到惊讶(您的示例不完整 - 否则我会尝试使用最新的 SVN 版本的 gcc 和 clang)。

【讨论】:

    【解决方案2】:

    这似乎是一个仍然存在的旧gcc bug。可能想给维护者一个友好的推动。

    解决方法可能是:

    #include <vector>
    #include <algorithm>
    #include <functional>
    #include <tuple>
    
    using namespace std;
    
    template<typename F>
    struct Foo {
      template<typename... Ts>
      void operator()(Ts... vs) const {
        auto t = tie(vs...);
    
        for_each(begin(l_), end(l_), 
                 [&t]( function<F> i) 
                 { 
                   // figure out the function arity and unpack the tuple
                   // onto it. This is could be more difficult than one
                   // thinks.
    
                   // i(vs...);
                 }
          );
      }
      vector< function< F > > l_;
    };
    

    【讨论】:

    • 谢谢我删除了 lambda:template&lt;typename... Ts&gt; void operator()(Ts... vs) const { for(auto i = begin(l_); i != end(l_); ++i) { (*i)(vs...); } }
    • 你仍然可以通过使用auto i : l_ 来改进它:)
    猜你喜欢
    • 2020-03-19
    • 2019-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-12
    • 2015-05-12
    • 2014-10-30
    相关资源
    最近更新 更多