C++20 新特性(12):使用模板语法的泛型lambda

C++20 新特性(12):使用模板语法的泛型lambda

编码文章call10242025-04-09 11:26:1617A+A-

在 C++14 中新增泛型lambda时,是使用基于 auto 的语法,比较简单但也带来一定的局限性,因此在 C++20 中进行改进,新增模板语法的泛型 lambda 。让我们先回顾一下基于 auto 语法的泛型 lambda ,以及其局限性,然后再看 C++20 新增的基于模板的泛型 lambda 。

(C++14)基于 auto 的泛型 lambda

C++14 中的泛型 lambda ,是使用 lambda 参数中的 auto 关键字来表示不同的类型,一个例子如下:

#include 
#include 
using std::cout, std::endl, std::string;

int main( int argc, char * argv[] )
{
    auto f1 = [] ( auto x, auto y ) { return x + y; };
    cout << &f1 << endl;
    string (*fp1)( string, string ) = f1;
    double (*fp2)( double, int ) = f1;
    cout << (void *)fp1 << " " << (void *)fp2 << endl;
    double a1 = f1( 2, 5.0 );
    string a2 = fp1( "2", "5.0" );
    cout << a1 << " " << a2 << endl;
    return 0;
}

上述代码编译和执行的结果为:

[smlc@test code]$ g++ -std=c++20 a12.cpp
[smlc@test code]$ ./a.out
0x7ffcef96de2f
0x401f18 0x401f4b
7 25.0

由于 lambda 表达式实际定义的是一个闭包类(ClosureType),通过重载 operator () 来提供仿函数的调用。通过 auto 关键字定义的泛型 lambda ,相当于如下的定义:

struct {
    template 
    auto operator() ( T x, U y ) const { return x + y; }
};

基于 auto 的泛型 lambda 的局限性

基于 auto 的泛型 lambda ,最主要的局限性,是 auto 描述是整个类型,而不能像模板一样细化类型的模式。例如如果想 lambda 的参数类型是某种类型的数组(std::vector),当前基于 auto 的泛型 lambda 无法表示,只能将参数定义成所有类型,然后再通过其他手段限制只能是数组类型(std::vector),同时,如果想获取数组里面的具体类型,也需要使用其他手段来获取。

template  struct is_std_vector : std::false_type { };
template  struct is_std_vector<std::vector> : std::true_type { };
auto f = [ ] ( auto vecType ) {
    static_assert( is_std_vector< decltype vectype>::value, "" );  // <1> 额外的判断std::vector
    using T = typename decltype( vecType )::value_type;  // <2> 使用其他手段获取数组的具体类型
    // ... other code ...  
};

其他还有很多类似的需要细化类型的情况,例如多个参数之间的类型有关联,或者是要去掉类型 const 等附加信息,这些都需要通过 decltype 来获取类型然后再进行各种处理,反而使代码更复杂了,因此增加模板语法的 lambda 是有必要的。

(C++20)新增基于模板的 lambda 语法

C++20中新增了基于模板的lambda语法,对于上面的情况可以更简洁的描述,和其他模板的语法也保持一致:

auto f = [ ] < typename t> ( std::vector vecType ) {  // <1> 无需额外判断std::vector,具体数组类型也可以直接使用T
    // ... other code ...  
}

语法上比较简单,不需要额外的 template 关键字,直接在 “ [ ] ” 和 “ ( ... ) ” 之间增加 “ < ...> ” 表示模板参数,然后在 lambda 参数和函数体中,就可以使用模板参数中描述的类型了。

基于模板的lambda也可以同时使用auto类型的参数,但不建议这样使用,混合使用这两种方式并不能带来额外的好处,反而使代码更加难懂。既然已经使用了模板,那么auto类型的参数也改为模板参数类型好了。


【往期回顾】

C++20 新特性(11):lambda对this的捕捉改进

C++20 新特性(10):字符串类型的改进

点击这里复制本文地址 以上内容由文彬编程网整理呈现,请务必在转载分享时注明本文地址!如对内容有疑问,请联系我们,谢谢!
qrcode

文彬编程网 © All Rights Reserved.  蜀ICP备2024111239号-4