CppCoreGuidelines里面的finally

CppCoreGuidelines里面的finally

https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#c30-define-a-destructor-if-a-class-needs-an-explicit-action-at-object-destruction

这种写法的主要设计思想:

1、使用模板参数typename A指示lambda表达式的类型,不使用std::function,避免std::function过于重量级的问题,不需要依赖任何标准库设施;

2、使用函数模板自动推导出类模板里的typename A,因为类模板(在C++17之前)不能自动推导模板参数。

template<typename A>
struct final_action {   // slightly simplified
    A act;
    final_action(A a) :act{a} {}
    ~final_action() { act(); }
};

template<typename A>
final_action<A> finally(A act)   // deduce action type
{
    return final_action<A>{act};
}

void test()
{
    auto act = finally([]{ cout << "Exit test\n"; });  // establish exit action
    // ...
    if (something) return;   // act done here
    // ...
} // act done here

实际上C++17以后已经不需要函数模板了,直接类模板就可以推导模板参数了:

template<typename A>
struct final_action {   // slightly simplified
    A act;
    final_action(A a) :act{a} {}
    ~final_action() { act(); }
};

void test()
{
    auto act = final_action([]{ cout << "Exit test\n"; });  // establish exit action
    // ...
    if (something) return;   // act done here
    // ...
} // act done here

完整版在microsoft/GSL里面,这个GSL代码库可以下载下来直接使用。

https://github.com/microsoft/GSL/blob/master/include/gsl/gsl_util

下面是代码节选,可以看出来它主要完善了复制和移动操作的相关内容:

1、移动构造被保留,用于支持从右值构造的语法;

2、复制构造被删除,用于防止finally被执行两次以上;

3、赋值运算符被删除,带捕获的lambda表达式只可构造,不可赋值;

4、使用bool invoke_标记避免调用已经被移走的lambda表达式;

5、添加了一些noexcept标记;

6、GSL_SUPPRESS是用来关闭某些CppCoreCheck建议的,可以直接注释掉。

// final_action allows you to ensure something gets run at the end of a scope
template <class F>
class final_action
{
public:
    explicit final_action(F f) noexcept : f_(std::move(f)) {}

    final_action(final_action&& other) noexcept : f_(std::move(other.f_)), invoke_(std::exchange(other.invoke_, false)) {}

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

    GSL_SUPPRESS(f.6) // NO-FORMAT: attribute // terminate if throws
    ~final_action() noexcept
    {
        if (invoke_) f_();
    }

private:
    F f_;
    bool invoke_{true};
};

// finally() - convenience function to generate a final_action
template <class F>
final_action<F> finally(const F& f) noexcept
{
    return final_action<F>(f);
}

template <class F>
final_action<F> finally(F&& f) noexcept
{
    return final_action<F>(std::forward<F>(f));
}
发布了29 篇原创文章 · 获赞 1 · 访问量 3393

猜你喜欢

转载自blog.csdn.net/defrag257/article/details/103941914