语法糖:萃取lambda表达式

本文介绍了在C++11中,如何利用模板技巧将non-capturing lambda表达式转化为等价的函数指针,以此简化异步编程中的回调函数。文中探讨了两种方案,包括使用独立函数和non-capturing lambda,并指出手动cast的冗余。通过lambda_decay模板,可以避免捕获型lambda在多线程环境中的安全性问题,提高代码的简洁性和可读性。
摘要由CSDN通过智能技术生成

背景

现在手头主负责的服务代码,基本上都用C++11来开发了,异步编程使用的是TAF的future/promise。

future的then函数,接受的是一个Callback对象,该对象通过promise::bind来生成。

Callback和bind是参考chromium的base::Callback,base::Bind实现的,该版本并不支持C++11,所以bind() 不接受 lambda 作为 Currying 的载体(Currying ,译为柯里化是把接受多个参数的函数变换成接受一个单一参数的函数,并且返回接受余下的参数且返回结果的新函数的技术)。

使用TAF的promise进行异步编程,如果能够使用lambda表达式来完成回调,代码将更加清晰直观。

由于TAF的bind不接受 lambda表达式,因此回调有以下两种直观的方案:

方案1:使用独立的函数来产生 Callback

优点是,直观明确而且很传统不容易出错;

缺点是,对于代码量少的回调函数,要单独写一个函数,造成阅读代码时的上下文割裂。

方案2:使用 non-capturing lambda,自己手动 cast 到函数指针

优点是,代码连贯,可读性好,不需要专门去写一个函数,编码方便;

缺点是,而且手动 cast 非常的冗长繁琐。

于是对方案2进行了一些改进,通过template来对lambda表达式进行traits,将 non-capturing lambda 自动转换为等价的函数指针。

萃取lambda表达式

lambda其实是个C++对象(函数对象),只不过里面包含int operator()(int a,int b)之类的成员函数,从而可以被当做函数来使用,因此lambda表达式被当做参数来传递时,其实是传递的C++对象。

借助模板的神力、我们可以将lambda表达式的函数类型给萃取(traits)出来:

#include <iostream>
#include <typeinfo>

#include <tuple>
#include <type_traits>

namespace stx
{

    namespace lambda_detail
    {
        // 将是否is_mutable、返回类型、参数包中元素个数、参数类型萃取出来
        template<class Ret, class Cls, class IsMutable, class... Args>
        struct types
        {
            using is_mutable = IsMutable;

            enum { arity = sizeof...(Args) };

            using return_type = Ret;

            
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值