#include #include #include #include template class at_exit { public: template at_exit(C2 &&_c, A2 &&..._a) : c(std::forward(_c)), a(std::forward(_a)...) {} at_exit(const at_exit &) = delete; at_exit(const at_exit &&) = delete; at_exit &operator=(const at_exit &) = delete; at_exit &operator=(const at_exit &&) = delete; ~at_exit() { std::apply(c, a); } private: std::decay_t c; std::tuple a; }; template at_exit(C, A...) -> at_exit; void msg(std::string_view s) { puts(s.data()); } struct S1 { void operator()(std::string_view s) const { puts(s.data()); } }; struct S2 { void print(std::string_view s) const { puts(s.data()); } }; at_exit global1([] { puts("[global1]: lambda"); }); at_exit global2(msg, "[global2]: function"); at_exit global3(S1{}, "[global3]: struct::operator()"); at_exit global4(&S2::print, S2{}, "[global4]: struct::method"); int main() { at_exit local1([] { puts("[local1]: lambda"); }); at_exit local2(msg, "[local2]: function"); at_exit local3(S1{}, "[local3]: struct::operator()"); at_exit local4(&S2::print, S2{}, "[local4]: struct::method"); }