diff --git a/defer.h b/defer.h new file mode 100644 index 0000000..e29d467 --- /dev/null +++ b/defer.h @@ -0,0 +1,45 @@ +#ifndef MAG_DEFER_H +#define MAG_DEFER_H +/** + * Zig-like defer macro for (gc)C and C++ + * + * Based on: + * https://gustedt.wordpress.com/2025/01/06/simple-defer-ready-to-use/ + * - but works with gcc(C), g++ and non-gcc c++ compilers. + * - so it only does not work for other C compilers. + * + * Rem.: This [[gnu::always_inline]] + * basically means __attribute__((always_inline)) + */ + +#ifdef __cplusplus +template +struct __df_st : T { + [[gnu::always_inline]] + inline + __df_st(T g) : T(g) { + // empty + } + [[gnu::always_inline]] + inline + ~__df_st() { + T::operator()(); + } +}; +#define __DEFER__(V) __df_st const V = [&](void)->void +#define defer __DEFER(__COUNTER__) +#define __DEFER(N) __DEFER_(N) +#define __DEFER_(N) __DEFER__(__DEFER_VARIABLE_ ## N) + +#else + +#define __DEFER__(F, V) \ + [[gnu::always_inline]] inline auto void F(int*); \ + [[gnu::cleanup(F)]] int V; \ + [[gnu::always_inline]] inline auto void F(int*) +#define defer __DEFER(__COUNTER__) +#define __DEFER(N) __DEFER_(N) +#define __DEFER_(N) __DEFER__(__DEFER_FUNCTION_ ## N, __DEFER_VARIABLE_ ## N) +#endif /* __cplusplus */ + +#endif /* MAG_DEFER_H */