如何在捕获 lambda 参数时使用模板化的 typedef?

Mar*_*vić 3 c++ lambda templates c++11

所以我一直在学习模板和 lambda 表达式,所以我尝试将两者结合起来。我正在尝试创建一个模板化的 typedef,它指定了 lambda 应该返回和接受的内容。它适用于非捕获 lambdas,但它不能处理任何捕获的 lambdas。这是我现在的代码:

template<typename T>
using L  = T(*)(T);

template<typename T>
T applyLambda(T var, L<T> lambda){
  return lambda(var);
}

int main() {
  
  const int a = 45;

  int b = applyLambda<int>(3, [] (int x)->int { // non capturing lambda
    return x+5;
  });

  std::cout << b << std::endl;

}
Run Code Online (Sandbox Code Playgroud)

但是,如果我将函数调用更改为:

int b = applyLambda<int>(3, [=] (int x)->int {
    return x+a;
  });
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

candidate function template not viable: no known conversion from
      '(lambda at main.cpp:15:31)' to 'L<int>' (aka 'int (*)(int)') for 2nd argument
T applyLambda(T var, L<T> lambda)
Run Code Online (Sandbox Code Playgroud)

现在我的问题是我需要在这里改变什么:

template<typename T>
using L  = T(*)(T);
Run Code Online (Sandbox Code Playgroud)

为了接受捕获的 lambda。

我确实意识到我总是可以这样做,但这不会指定 lambda 返回类型和参数

template<typename T, typename LF>
T applyLambda(T var, LF lambda){
Run Code Online (Sandbox Code Playgroud)

son*_*yao 5

L被标记为函数指针类型。没有捕获列表的Lambda可以隐式转换为函数指针,但带有捕获列表的 lambda 不能。

只有当 lambda 表达式的捕获列表为空时,才定义此用户定义的转换函数

你可以std::function改用。

template<typename T>
using L  = std::function<T(T)>;
Run Code Online (Sandbox Code Playgroud)

居住

顺便说一句:您可以使用std::type_identity(自 C++20 起)applyLambda从推导中排除第二个函数参数(有关详细信息,请参阅非推导上下文),然后模板参数推导将适用于您,无需再次指定模板参数。对于函数指针版本也是如此。(如果您的编译器不支持 C++20,则很容易制作自己的type_identity.)例如

template<typename T>
T applyLambda(T var, std::type_identity_t<L<T>> lambda){
  return lambda(var);
}
Run Code Online (Sandbox Code Playgroud)

然后

int b = applyLambda(3, [=] (int x)->int {
  return x+a;
});
Run Code Online (Sandbox Code Playgroud)

居住

  • 1+ 表示“类型身份”。 (2认同)