| 54 | // destroyed. Cleanup<F> is the return type of gtl::MakeCleanup(F). |
| 55 | template <typename F> |
| 56 | class Cleanup { |
| 57 | public: |
| 58 | Cleanup() : released_(true), f_() {} |
| 59 | |
| 60 | template <typename G> |
| 61 | explicit Cleanup(G&& f) // NOLINT |
| 62 | : f_(std::forward<G>(f)) {} // NOLINT(build/c++11) |
| 63 | |
| 64 | Cleanup(Cleanup&& src) // NOLINT |
| 65 | : released_(src.is_released()), f_(src.release()) {} |
| 66 | |
| 67 | // Implicitly move-constructible from any compatible Cleanup<G>. |
| 68 | // The source will be released as if src.release() were called. |
| 69 | // A moved-from Cleanup can be safely destroyed or reassigned. |
| 70 | template <typename G> |
| 71 | Cleanup(Cleanup<G>&& src) // NOLINT |
| 72 | : released_(src.is_released()), f_(src.release()) {} |
| 73 | |
| 74 | // Assignment to a Cleanup object behaves like destroying it |
| 75 | // and making a new one in its place, analogous to unique_ptr |
| 76 | // semantics. |
| 77 | Cleanup& operator=(Cleanup&& src) { // NOLINT |
| 78 | if (!released_) f_(); |
| 79 | released_ = src.released_; |
| 80 | f_ = src.release(); |
| 81 | return *this; |
| 82 | } |
| 83 | |
| 84 | ~Cleanup() { |
| 85 | if (!released_) f_(); |
| 86 | } |
| 87 | |
| 88 | // Releases the cleanup function instead of running it. |
| 89 | // Hint: use c.release()() to run early. |
| 90 | F release() { |
| 91 | released_ = true; |
| 92 | return std::move(f_); |
| 93 | } |
| 94 | |
| 95 | bool is_released() const { return released_; } |
| 96 | |
| 97 | private: |
| 98 | static_assert(!std::is_reference<F>::value, "F must not be a reference"); |
| 99 | |
| 100 | bool released_ = false; |
| 101 | F f_; |
| 102 | }; |
| 103 | |
| 104 | template <int&... ExplicitParameterBarrier, typename F, |
| 105 | typename DecayF = typename std::decay<F>::type> |
no test coverage detected