泛型lambda是c++++14引入的特性,允许参数使用auto类型,由编译器自动推导具体类型。1. 它可用于stl算法中简化代码,例如一个lambda可同时用于int和double排序;2. 避免显式模板定义,如统一的打印函数;3. 支持多参数auto类型,适用于不同类型比较;但需注意不能跨类型混用、返回值类型须一致及调试时不易查看实际类型,此外可结合decltype(auto)保留返回值引用语义。
C++14引入了对泛型lambda表达式的支持,也就是允许lambda的参数使用
auto
类型。这使得我们可以写出更简洁、通用的代码,尤其在STL算法中非常实用。
下面是一些使用带
auto
参数的lambda表达式的技巧和注意事项。
什么是泛型lambda?
泛型lambda是指lambda表达式的参数类型是
auto
,这样编译器会根据调用时传入的参数类型自动推导出具体的类型。
立即学习“C++免费学习笔记(深入)”;
例如:
auto func = [](auto x) { return x + x; };
这个lambda可以接受任何类型的参数,只要该类型支持
+
操作。
泛型lambda的实际应用场景
1. 用于STL算法中简化代码
在处理容器的时候,我们经常需要写一些简单的函数对象,比如排序、查找等。泛型lambda可以让我们避免为每种类型单独写函数或函数对象。
示例:
std::vector<int> vi = {3, 1, 4}; std::vector<double> vd = {2.5, 1.2, 3.7}; std::sort(vi.begin(), vi.end(), [](auto a, auto b) { return a > b; }); std::sort(vd.begin(), vd.end(), [](auto a, auto b) { return a > b; });
这里一个lambda就可以同时用于int和double的排序,不需要分别写两个函数或模板函数。
2. 避免显式模板定义
有时候你可能想写一个通用的转换或者包装逻辑,但又不想自己去写完整的模板类或函数。这时候泛型lambda就很有用了。
比如你想写一个统一的打印函数:
auto print = [](auto&& val) { std::cout << val << std::endl; }; std::for_each(vi.begin(), vi.end(), print); std::for_each(vd.begin(), vd.end(), print);
3. 结合多参数使用
泛型lambda也可以有多个参数,每个都可以是
auto
类型:
auto compare = [](auto a, auto b) { return a < b; };
这样的lambda可以用于不同类型之间的比较(当然前提是这些类型之间确实可以比较)。
使用泛型lambda需要注意的地方
-
不能跨类型混用:虽然lambda的参数是
auto
,但如果你在函数体内写了只适用于特定类型的代码,那它实际上就只能用于那种类型。
比如下面这个lambda,在遇到字符串时就会出错:
auto add = [](auto a, auto b) { return a + b; };
如果传入的是
std::string*
,那结果就是指针加法,而不是字符串拼接。
-
返回值类型必须一致:如果lambda返回的值类型依赖于输入参数的类型,那么所有路径的返回值类型最好能一致,否则可能会导致编译错误。
-
调试时不容易看到实际类型:因为lambda是编译器自动生成的匿名类,所以在调试器里看变量类型可能会不太直观。
小技巧:结合
decltype(auto)
decltype(auto)
使用
如果你希望lambda返回的类型也能自动推导,并且保留引用语义,可以使用
decltype(auto)
作为返回类型:
auto get = [](auto& container, int index) -> decltype(auto) { return container[index]; };
这样可以在不显式指定返回类型的情况下,保留返回值的引用特性。
基本上就这些。泛型lambda是个很实用的小工具,尤其是在快速开发和写回调函数的时候。不过要注意它的适用范围,别让它变成“万能”却不可控的黑盒。
评论(已关闭)
评论已关闭