#pragma once #ifndef TCG_AUTO_H #define TCG_AUTO_H #include "base.h" #include "traits.h" /* \file auto.h \brief This file contains template classes able to perform special operations upon instance destruction. \details These classes can be useful to enforce block-scoped operations at a block's entry point, considering that a block end can be far away, or the function could return abruptly at several different points. */ namespace tcg { //******************************************************************************* // tcg::auto_type definition //******************************************************************************* struct _auto_type { mutable bool m_destruct; public: _auto_type(bool destruct) : m_destruct(destruct) {} _auto_type(const _auto_type &other) : m_destruct(other.m_destruct) { other.m_destruct = false; } _auto_type &operator=(const _auto_type &other) { m_destruct = other.m_destruct, other.m_destruct = false; return *this; } }; typedef const _auto_type &auto_type; //******************************************************************************* // tcg::auto_func definition //******************************************************************************* template struct auto_zerary : public _auto_type { Op m_op; public: auto_zerary(bool destruct = true) : _auto_type(destruct) {} ~auto_zerary() { if (this->m_destruct) m_op(); } }; //-------------------------------------------------------------------- template ::arg1_type> struct auto_unary : public _auto_type { T m_arg1; Op m_op; public: auto_unary(bool destruct = true) : _auto_type(destruct) {} auto_unary(Op op, T arg, bool destruct = true) : _auto_type(destruct), m_arg1(arg), m_op(op) {} ~auto_unary() { if (this->m_destruct) m_op(m_arg1); } }; //-------------------------------------------------------------------- template ::arg1_type, typename T2 = typename function_traits::arg2_type> struct auto_binary : public _auto_type { T1 m_arg1; T2 m_arg2; Op m_op; public: auto_binary(bool destruct = true) : _auto_type(destruct) {} auto_binary(Op op, T1 arg1, T2 arg2, bool destruct = true) : _auto_type(destruct), m_arg1(arg1), m_arg2(arg2), m_op(op) {} ~auto_binary() { if (this->m_destruct) m_op(m_arg1, m_arg2); } }; //******************************************************************************* // Helper functions //******************************************************************************* template auto_zerary make_auto(Op op, bool destruct = true) { return auto_zerary(op, destruct); } template auto_unary make_auto(Op op, T &arg1, bool destruct = true) { return auto_unary(op, arg1, destruct); } template auto_unary make_auto(Op op, const T &arg1, bool destruct = true) { return auto_unary(op, arg1, destruct); } template auto_binary make_auto(Op op, T1 &arg1, T2 &arg2, bool destruct = true) { return auto_binary(op, arg1, arg2, destruct); } template auto_binary make_auto(Op op, const T1 &arg1, T2 &arg2, bool destruct = true) { return auto_binary(op, arg1, arg2, destruct); } template auto_binary make_auto(Op op, T1 &arg1, const T2 &arg2, bool destruct = true) { return auto_binary(op, arg1, arg2, destruct); } template auto_binary make_auto(Op op, const T1 &arg1, const T2 &arg2, bool destruct = true) { return auto_binary(op, arg1, arg2, destruct); } //******************************************************************************* // tcg::auto_reset definition //******************************************************************************* template class auto_reset { typedef T var_type; public: var_type &m_var; public: auto_reset(var_type &var) : m_var(var) {} ~auto_reset() { m_var = val; } private: auto_reset(const auto_reset &); auto_reset &operator=(const auto_reset &); }; //******************************************************************************* // tcg::auto_backup definition //******************************************************************************* template struct auto_backup { typedef T var_type; public: var_type m_backup; var_type *m_original; public: auto_backup() : m_original() {} auto_backup(var_type &original) : m_original(&original), m_backup(original) {} auto_backup(var_type *original) : m_original(original) { if (m_original) m_backup = *m_original; } ~auto_backup() { if (m_original) *m_original = m_backup; } void reset(T &original) { m_original = &original; m_backup = original; } void reset(T *original) { m_original = original; if (m_original) m_backup = *original; } T *release() { T *original = m_original; m_original = 0; return original; } private: auto_backup(const auto_backup &); auto_backup &operator=(const auto_backup &); }; } // namespace tcg #endif // TCG_AUTO_H