46 lines
1.1 KiB
C
46 lines
1.1 KiB
C
|
#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 */
|