简体   繁体   English

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

[英]How to use a templated typedef on capturing lambda parameter?

So I've been learning about templates and lambdas so I tried to combine the two.所以我一直在学习模板和 lambda,所以我尝试将两者结合起来。 I am trying to create a templated typedef that specifies what the lambda is supposed to return and accept.我正在尝试创建一个模板化的 typedef,它指定 lambda 应该返回和接受的内容。 It works well for non capturing lambdas but it cannot handle any lambdas that capture.它适用于非捕获 lambda,但它无法处理任何捕获的 lambda。 This is my code for now:这是我现在的代码:

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;

}

But if I change the function call to this:但是,如果我将 function 调用更改为:

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

I get the following error:我收到以下错误:

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)

Now my question is what do I need to change here:现在我的问题是我需要在这里改变什么:

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

In order to accept lambdas that capture.为了接受捕获的 lambda。

I do realize I could always do it like this but that would not specify lambda return type and parameters我确实意识到我总是可以这样做,但不会指定 lambda 返回类型和参数

template<typename T, typename LF>
T applyLambda(T var, LF lambda){

L is decalred as function pointer type. L标记为 function 指针类型。 Lambdas without capture list could convert to function pointer implicitly, but lambdas with capture list can't.没有捕获列表的Lambda可以隐式转换为 function 指针,但带有捕获列表的 lambda 不能。

This user-defined conversion function is only defined if the capture list of the lambda-expression is empty.这种用户定义的转换 function仅在 lambda 表达式的捕获列表为空时定义。

You can use std::function instead.您可以改用std::function

template<typename T>
using L  = std::function<T(T)>;

LIVE居住

BTW: You can use std::type_identity (since C++20) to exclude the 2nd function argument of applyLambda from deduction (see non deduced context for details), then template argument deduction would work for you and no need to specify the template argument again.顺便说一句:您可以使用std::type_identity (C++20 起)从推导中排除 applyLambda 的第二个 function 参数(有关详细信息,请参阅非推导上下文),然后模板参数推导对您applyLambda ,无需指定模板再次争论。 This is true for the function pointer version too. function 指针版本也是如此。 (If your compiler doesn't support C++20 it's quite easy to make your own type_identity .) Eg (如果您的编译器不支持 C++20,则很容易制作自己的type_identity 。)例如

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

then然后

int b = applyLambda(3, [=] (int x)->int {
  return x+a;
});

LIVE居住

You need to use std::function objects instead of naked lambdas.您需要使用std::function对象而不是裸 lambdas。

Unfortunately for some complex strange reasons each lambda is a different type on its own and there is no easy way to declare a variable or a parameter of type lambda.不幸的是,由于一些复杂的奇怪原因,每个 lambda 本身都是不同的类型,并且没有简单的方法来声明 lambda 类型的变量或参数。 Even if you succeed (eg using decltype ) the variable you declare is useless because you can only assign it the specific lambda you got the type from and not any another one.即使您成功(例如使用decltype ),您声明的变量也是无用的,因为您只能将其分配给您从中获得类型的特定 lambda 而不能分配任何其他类型。

In other words:换句话说:

void bar() {
    int x = 0;
    auto inc1 = [&x](){ x++; };
    auto inc2 = [&x](){ x++; };
    inc1 = inc2; // Error, type is different despite EVERYTHING being identical
}

std::function is designed to solve this limitation so excluding passing them to template functions (and understanding the implications of that) you should never use parameters of type lambda, and use std::function objects instead. std::function旨在解决此限制,因此不包括将它们传递给模板函数(并理解其含义),您永远不应使用 lambda 类型的参数,而应使用std::function对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM