【问题标题】:How to pass reference to function with lambda如何使用 lambda 传递对函数的引用
【发布时间】:2016-07-02 18:51:34
【问题描述】:

我有一个数据成员的类型:

std::function<T(T&, T&)>&

构造函数接受相同类型的参数。

我应该如何使用 lambdas 发送这样的函数?

我试过了

MyClass tmp([](Foo &a, Foo &b) { return a+b; }, ...);

但它失败了。

例如:

main.cpp

#include "MyClass.h"

int main()
{
    MyClass a([](int x, int y) { return x+y;});

    return 0;
}

MyClass.h

#pragma once

#include <functional>

class MyClass
{
    public:
        MyClass(std::function<int(int, int)>&) noexcept;
    private:
        std::function<int(int, int)>& fun;
};

【问题讨论】:

  • 失败怎么办?创建minimal reproducible example
  • 为什么需要将非const 引用 传递给std::function
  • @nwp:失败的方式是将prvalue传递给采用非const引用的函数失败。
  • @nwp 对不起,我添加了你的要求。
  • @NicolBolas 不,试试我发布的示例。

标签: c++ lambda pass-by-reference


【解决方案1】:

您将 lambda 传递给 std::function &amp;。 lambda 不是std::function,所以它不能直接工作。但是,lambda 可以转换为 std::function,因此必须构建一个临时的 std::function 来保存 lambda。

由于您使用std::function &amp; C++ 假定您要修改该值,否则通过非常量引用获取它是没有意义的。修改一个临时的没有效果,所以这没有意义,所以C++不允许这样做。

解决此问题的一种方法是发送const std::function &amp;。这样就没有临时修改。

另一种方法是传递您在main 中创建的实际std::function

另一种方法是创建一个模板,将其参数转发给std::function

class MyClass
{
    public:
        template <class T>
        MyClass(T &&t)
            : fun(std::forward<T>(t)){}
    private:
        std::function<int(int, int)> fun;
};

这样MyClass 可以获取任何东西并使用它来构造fun。请注意,fun 不再是参考。 std::function 必须存在于某个地方,因为它是 MyClass 的一部分,所以将 std::function 的生命周期与 MyClass 联系起来是有意义的。

如果您真的希望 fun 成为参考,您需要为它找到一个位置并确保它一直留在那里直到 MyClass a; 被销毁。我不推荐这条路线,因为越来越难以确保生命周期是正确的。

您也可以直接存储 lambda,但这有点棘手,并且取决于您对 MyClass 的实际操作,它可能不可行。

【讨论】:

  • “另一种方法是创建一个仅转发它的参数的模板” - 与仅按值获取 std::function 并从中移动构造 fun 相比,这确实没有任何优势。甚至是您之前提出的通过const &amp; 获取它并从中复制构建的建议。你所做的意味着类型特征不能再检测到 MyClass 不能从 int 构造,因为构造函数实例化失败太晚了,SFINAE 无法启动。
  • @nwp 我试过这样的临时函数:auto fun = [](int x, int y)-&gt; int&amp; { return x+y;}; 但它不起作用。
  • @user6180573 我的意思是std::function&lt;int(int,int)&gt; f = [](int x, int y) { return x+y;};,然后是MyClass a(f);
  • @user6180573 那是因为fun的类型不是std::function。您需要指定std::function&lt;int(int, int)&gt; fun = [](int x, int y) { return x+y; };
  • @nwp 现在它不适用于上面的构造函数:(
猜你喜欢
  • 1970-01-01
  • 2010-09-27
  • 2016-03-24
  • 1970-01-01
  • 2012-02-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-22
相关资源
最近更新 更多