c_mem_safety/defer.h

46 lines
1.1 KiB
C
Raw Normal View History

#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<typename T>
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 */