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