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