接受代表各种参数函数的lambda的类方法

时间:2019-01-09 18:49:01

标签: c++ lambda std-function

我想将函数传递给泛型方法,因此泛型类可以调用不需要args,一个arg,两个args等的函数。

我看过可变参数模板,但是我不喜欢这种语法。之前的SO问题建议传递lambda,并包装函数:

https://stackoverflow.com/a/48976528/997112

答案是:

void run_callback(std::function<void()>& func) 
{
    func();
}

run_callback([]{ func_without_params(); });

因此我添加了一个不需要参数的方法:

void func_without_params()
{
    std::cout << "x" << std::endl;
}

但是当我打电话时:

run_callback([]{ func_without_params(); });

在VS2013中,Intellisense检测到错误,并且我得到了编译器错误:

error C2664: 'void run_callback(std::function<void (void)> &)' :
cannot convert argument 1 from
'main::<lambda_de925f4d5cd926a8bb664f9c057a7a19>' to
'std::function<void (void)> &'

什么是main::<lambda_de925f4d5cd926a8bb664f9c057a7a19>类型?我没有完全理解错误。

2 个答案:

答案 0 :(得分:3)

除了邪恶的编译器扩展之外,您无法使用非l值的内容初始化非常量引用(参数func)。将参数设为const:

#include <functional>
#include <iostream>

void run_callback(std::function<void()> const &func)
{
    func();
}

void func_without_params()
{
    std::cout << "x" << std::endl;
}

int main()
{
    run_callback([] { func_without_params(); });
}

答案 1 :(得分:1)

  

什么是main::<lambda_de925f4d5cd926a8bb664f9c057a7a19>类型?

有关lambda表达式的参考文献是什么

  

lambda表达式是唯一未命名的prvalue表达式   非联盟非聚合类类型,称为闭包类型,它是   在最小的块范围,类范围或名称空间范围内声明   包含lambda表达式。

仅对程序员未命名,编译器知道此名称,在您的情况下,lambda_de925f4d5cd926a8bb664f9c057a7a19是闭包类型的名称。 main是指在其中定义了闭合类型的函数。

您可以使用cppinsights来查看幕后情况。 cppinsights 使用不接受将Rvalue绑定到Lvalue引用的Clang,因此将代码更改为:

void run_callback(std::function<void()> func) // take by value

cppinsights 的输出为:

int main() { // scope of closure type

  class __lambda_14_16 { // closure type
    public: inline /*constexpr */ void operator()() const
    {
      func_without_params();
    }

  };

  run_callback(std::function<void ()>(__lambda_14_16{}));
}