定义函数时,哪种类型是lambda函数/表达式

When defining a function, what type is a lambda function/expression?

本文关键字:函数 lambda 表达式 类型 种类 定义      更新时间:2023-10-16

我想定义一个函数,该函数(除了通常的输入参数)lambda函数。我想尽可能限制该功能(其自己的输入和返回类型)。

int myfunc( const int a, LAMBDA_TYPE (int, int) -> int mylamda )
{
    return mylambda( a, a ) * 2;
}

使我可以称为以下功能:

int input = 5;
myfunc( input, [](int a, int b) { return a*b; } );

定义myfunc的正确方法是什么?

是否有一种方法可以定义默认的lambda?这样:

int myfunc( const int a, LAMBDA_TYPE = [](int a, int b) { return a*b; });

如果您服用std::function<int(int,int)>,它将有开销,但它会做您想要的。它甚至会在C 14中正确超载。

如果您不想键入删除和std::function的分配开销,则可以这样做:

template<
  class F,
  class R=std::result_of_t<F&(int,int)>,
  class=std::enable_if_t<std::is_same<int,R>{}>
>
int myfunc( const int a, F&& f )

或检查转换性到int而不是相同。这是Sfinae解决方案。 1

这将正确负载。我用一些C 14个功能进行简洁。将blah_t<?>替换为C 11中的typename blah<?>::type

另一个选项是static_assert类似的子句。这会生成最佳错误消息。

最后,您可以使用它:如果无法按照您的使用方式使用代码。

在C 1Z概念中,将有更轻松/更少的代码沙拉来执行Sfinae解决方案。


1 在某些编译器上std::result_of与Sfinae无法播放。在这些上,用decltype(std::declval<F&>()(1,1))替换。除非您的编译器不支持C 11(例如MSVC 2013和2015),这将有效。(幸运的是2013/3015具有不错的result_of)。

有两种替代方案,类型的 std::function<signature>强迫特定的签名符合您的问题的线条,但它施加了一些额外的成本(主要是不能在一般而言。替代方法是使用模板将最后一个参数作为通用对象。从性能的角度来看,这种方法可以更好,但是您将语法检查留给了编译器(我认为这不是问题)。其中一条评论提到将lambda作为功能指针 ,但这仅适用于没有捕获的lambdas。

我个人会选择第二种选择:

template <typename Fn>
int myFunc(const int a, Fn&& f) {
   return f(a, a) * 2;
}

请注意,虽然这不会明确强制特定签名,但编译器将强制执行f使用两个int可调用,并产生可以乘以2并转换为int的东西。