Skip to content

Instantly share code, notes, and snippets.

@p2004a
Last active May 24, 2024 01:29
Show Gist options
  • Save p2004a/045726d70a490d12ad62 to your computer and use it in GitHub Desktop.
Save p2004a/045726d70a490d12ad62 to your computer and use it in GitHub Desktop.
Simple defer macro for c++
// SPDX-FileCopyrightText: 2015 Marek Rusinowski
// SPDX-License-Identifier: MIT
#include <memory>
#include <cstdio>
template<typename F>
class defer_finalizer {
F f;
bool moved;
public:
template<typename T>
defer_finalizer(T && f_) : f(std::forward<T>(f_)), moved(false) { }
defer_finalizer(const defer_finalizer &) = delete;
defer_finalizer(defer_finalizer && other) : f(std::move(other.f)), moved(other.moved) {
other.moved = true;
}
~defer_finalizer() {
if (!moved) f();
}
};
struct {
template<typename F>
defer_finalizer<F> operator<<(F && f) {
return defer_finalizer<F>(std::forward<F>(f));
}
} deferrer;
#define TOKENPASTE(x, y) x ## y
#define TOKENPASTE2(x, y) TOKENPASTE(x, y)
#define defer auto TOKENPASTE2(__deferred_lambda_call, __COUNTER__) = deferrer << [&]
void f() {
FILE *f = fopen("asdasd", "r");
defer {
fclose(f);
};
}
// Compiler optimizes it nicely: http://goo.gl/XAGl6A
@dolmens
Copy link

dolmens commented May 18, 2022

How can I make this a header file, maybe change deferrer to a static singleton instance?

@p2004a
Copy link
Author

p2004a commented May 30, 2022

@dolmens I know about 2 ways:

  1. Add static to the deferrer singleton as you suggest.

  2. struct deferrer {
         // ...
    };
    extern deferrer deferrer_object;

    and then have a single c++ file with deferrer deferrer_object;

The 1 is cleaner IMHO ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment