C++11中实现类似golang的defer

golang中有个处理异常的关键字defer

应用场景类似于java里面的finally,使用的时候就是所有的其他的正常的函数进程执行完毕之后都要执行defer。也就是被defer修饰的函数或者语句都是等到所有的作用域内部的函数执行完毕才会执行。

defer的这个特性正好契合C++的RAII。那我们能不能利用RAII实现defer的功能呢。

思路

RAII

我们知道对象在作用域结束自动析构,那我们在使用defer的时候创建某个对象,指定某个操作,然后在析构的时候执行这个操作。

std::function

C++11引入了std::functionstd::bindlambda,我们可以利用这些将需要defer的操作包装成std::function<void()>对象存储到一个对象中,当对象析构时,调用这个std::function<void()>对象。

如何像关键字一样使用?

golang的使用方式时这样的

defer file.close();

按照之前的思路,C++的使用方式是这样的

defer_t defer([&file]() {
	file.close();
});

或者

defer_t defer;
defer.set([&file]() {
	file.close();
});

这个和golang的使用方式都相去甚远,关键是不易用。

那我们一个一个问题解决。

首先,每次都自己定义个变量太麻烦。能不能自动定义?

defer auto DEFER_CREATE_NAME(defer_, __COUNTER__)

这个defer_name每次使用生成不一样呢?
使用宏生成不同名称

#define DEFER_CONCAT_NAME(l, r) l##r
#define DEFER_CREATE_NAME(l, r) DEFER_CONCAT_NAME(l, r)
#define defer auto DEFER_CREATE_NAME(defer_, __COUNTER__)

还有个问题,如何传入std::function呢?
operator+-*/
我们定义一个操作符,使用操作符添加std::function

实现
class defer_t final {
public:
    template <typename F>
    explicit defer_t(F&& f) noexcept : f_{std::forward<F>(f)} {
    }

    ~defer_t() {
        if (f_) {
            f_();
        }
    }

    defer_t(const defer_t&) = delete;
    defer_t& operator=(const defer_t&) = delete;

    defer_t(defer_t&& rhs) noexcept : f_{std::move(rhs.f_)} {
    }

    defer_t& operator=(defer_t&& rhs) noexcept {
        f_ = std::move(rhs.f_);
        return *this;
    }

private:
    std::function<void()> f_;
};

class defer_maker final {
public:
    template <typename F>
    defer_t operator+(F&& f) {
        return defer_t{std::forward<F>(f)};
    }
};

#define DEFER_CONCAT_NAME(l, r) l##r
#define DEFER_CREATE_NAME(l, r) DEFER_CONCAT_NAME(l, r)
#define defer auto DEFER_CREATE_NAME(defer_, __COUNTER__) = defer_maker{} +
#define defer_scope defer [&]
使用
defer [&file]() {
	file.close();
};

defer_scope {
	file.close();
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值