请看看我的快速博客文章,在那里我会告诉你一些有趣的兰姆达的例子。你知道如何写递归的 lambda 吗?把它们存放在容器里?或在编译时调用?

请参阅本文中的介绍。

1. 递归兰姆达与std::function

编写递归函数相对简单:在函数定义中,可以通过其名称调用同一函数。羔羊怎么样?

C++

 

x
1
 
1
int() |
2
自动因子= (intn) =
3
    };

5
回报因子5);
6
}

这个,可惜不编译 ... ...

我们如何解决这个问题?

一种方法就是使用 std::function

C++

 

x
1
 
1
[int ()]

4
conststd::函数<intint>factorial=因子= 和因子factorial=(intintn) |
5
返回n>1n*因子 (n-11;
6
  };
7
回报因子5);
8
}

这一次, 我们需要 factorial 捕捉, 然后我们可以参考它在羔羊体内1px;"[int ()]

2
康斯特自动因子=intn) =
3
constautofact_impl[ (intnconst自动&impl->int]
4
返回n>1n_impln-1impl1;
5
  };
6
返回fact_implnfact_impl
7
回报因子5);

9
}

这一次,它甚至更加复杂(但不需要大量使用 std::function 。它使用内部 lambda 进行主计算,然后作为泛型参数传递。

但我想知道: 你曾经使用过递归的羔羊吗?或者,最好依靠递归函数(似乎使用和写入要舒服多了)。

2. constexpr 兰达斯

但这还不是全部与递归:)

由于 C++17,我们可以编写将呼叫运算符定义为 的 constexpr lambda。我们可以使用此属性,将递归示例扩展到:

C++

 

x
1
 
1
[constexpr auto 自动因子] [(int n) ]

3
constexpr自动fact_impl[ [(intintnconst自动&impl->int]
4
返回n>1n_impln-1impl1;
5
  };
6
返回fact_implnfact_impl
7
static_assert5= 120);

9
}

在 C++20 中,您甚至可以 consteval 应用标记只能在编译时评估的 lambda。

3. 将兰姆达斯存放在容器中

这可能有点欺骗...但理论上我们可以把羔羊存放在容器里

虽然闭包类型删除了默认构造函数(除非它是 C++20 中的无状态 lambda),但我们可以在 C++20 中执行一点哈克并将其所有 lambda 存储为 std::function 对象。例如:

C++

 

x
1
28
 
1
#include <iostream>

3
#include <矢量>
4

5
int() |
6
std::向量<std::函数<std::字符串conststd::字符串&;)>>vecFilters;
7

8
vecFiltersemplace_back(+)(constconststd::字符串x
9
返回x="惊人"
10
vecfilters.emplace_back(*(const std::字符串 x) |

12
返回x="现代"
13
  });
14
vecFiltersemplace_back(+)(constconststd::字符串x
15
返回x="C++"
16
  });
17
vecFiltersemplace_back(+)(constconststd::字符串x
18
    });

20

21
conststd::字符串str="你好";
22
自动温度=str;
23

24
用于自动和输入FuncvecFilters
25
温度=条目乐趣 (温度);
26

27
}

4.通用的羔羊和帮助与扣除

C++14为 lambdas 带来了一个重要的补充:通用 lambda 参数。下面是一个示例,它显示了它为什么有用:

C++

 

x
1
16
 
1
#include <iostream>

3
#include <地图>
4
#include <字符串>
5

6
int() |
7
conststd::地图<std::字符串int>数字
8
  "一"1 +, [二"2"三"3]
9
  };
10

11
[(const std::p航空<std:字符串int>&条目)]

13
std::cout<<条目一个 <<\n;" = "<<entry二个 <<\n''\n';
14
}
15
  );
16
}

你知道这有什么错误吗?参数类型是否在 内部 lambda 中适当指定 for_each

我指定了: const std::pair<std::string, int>& entry

但它是错误的,因为地图中的键/值对的类型是:

这就是为什么编译器必须创建不需要的临时副本,然后将它们传递给我的 lambda。

我们可以通过使用来自 14 岁的通用 lambda 来C++问题。

C++

 

x
1
 
1
std::for_eachstd:: 开始数字std:: 结束数字
2
  [(康斯特auto自动和条目entry)]
3
std::cout<<条目一个 <<\" = "n;entry

1px;">   }

5
);

现在,这些类型匹配,并且不会创建其他副本。

5. 返回兰姆达

如果要从函数返回 lambda(例如,对于部分函数应用程序,咖喱),则不简单,因为您不知道闭包对象的确切类型。

在C++11 中,一种方法就是使用 std::function

C++

 

x
1
10
 
1
{std::函数<int> CreateLambdaint y>

4
返回=y=(intx返回x=y; =;
5
}
6

7
int() |
8
自动lam=CreateLambda10
9
返回lam32);
10
自动创建Lambdaint y

2
返回=y=(intx返回x=y; =;
3
}
4

5
int() |
6
自动lam=CreateLambda10
7
返回lam32);
Comments are closed.