【问题标题】:Method to store C++ lambda: template vs non-template form?存储 C++ lambda 的方法:模板与非模板形式?
【发布时间】:2020-11-17 00:48:27
【问题描述】:

在接收和存储 lambda 函数时,我通常会看到这样的情况:

struct foo {
    std::function<void()> myFunc;

    template<typename F>
    void foo(F&& func) {
        myFunc = std::move(func);
    }
};

上面的表格比下面的表格有什么优势吗?

struct foo {
    std::function<void()> myFunc;

    void foo(std::function<void()>&& func) {
        myFunc = std::move(func);
    }
};

我正在使用 C++17。

【问题讨论】:

  • 请注意:更直接可比较的场景是第二个示例使用按值传递:void foo(std::function&lt;void()&gt; func) ...

标签: c++ templates lambda arguments c++17


【解决方案1】:

第一种形式

 template<typename F>
    void foo(F&& func) {
        myFunc = std::move(func);
    }

F&amp;&amp; 是一个转发 引用,因此您对std::move() 的使用不正确——您应该改用std::forward&lt;F&gt;(func)。应用修复后,此表单将与左值和右值参数一起正常工作。

第二种形式

void foo(std::function<void()>&& func) {
        myFunc = std::move(func);
    }

std::function&lt;void()&gt;&amp;&amp; func 是一个 rvalue 引用,因此您只能使用右值调用 foo(),这可能不是您想要的。

【讨论】:

  • 所以如果我想要将 lambda 参数限制为右值引用,那么 (2) 是否正确?它不会执行任何额外的分配吗?
  • 我不明白为什么应该这样做。在这两种情况下,都会有一个分配来构造 std::function。
  • 那么,如果我在 (1) 中将 std::move 替换为 std::forward,那么唯一的区别将是 (1) 接受左值和右值,而 (2) 限制为右值?
  • rvalue 的另一个区别是,在第一种情况下调用仿函数的移动 ctor,在第二种情况下调用 std::function 的移动 ctor。差别不大。
猜你喜欢
  • 1970-01-01
  • 2011-07-24
  • 2015-03-15
  • 2011-12-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-08
相关资源
最近更新 更多