/* Generated by Together */

#ifndef AUTOPOINTER_H
#define AUTOPOINTER_H

namespace KasperskyLicensing {

namespace Implementation { void Deallocate(void*); }
	
// http://www.josuttis.com/libbook/auto_ptr.html

template <class T> class AutoPointer
{
	template <class U> struct AutoPointerRef
	{
		AutoPointerRef(AutoPointer& rhs)
			: ref(rhs) {}

		AutoPointer<U>& ref;
	};
public:

	typedef T ElementType;

	explicit AutoPointer(T* p = 0) throw()
		: ptr(p) {}

	AutoPointer(AutoPointer& rhs) throw()
		: ptr(rhs.Release()) {}

	AutoPointer(AutoPointerRef<T> rhs) throw()
		: ptr(rhs.ref.Release()) {}

	template<class C>
	operator AutoPointer<C>() throw()
		{ return (AutoPointer<C>(*this)); }

	template<class C>
	operator AutoPointerRef<C>() throw()
		{ return (AutoPointerRef<C>(*this)); }

	template<class C>
	AutoPointer<T>& operator=(AutoPointer<C>& rhs) throw()
	{
		Reset(rhs.Release());
		return (*this);
	}

	AutoPointer<T>& operator=(AutoPointer<T>& rhs) throw()
	{
		Reset(rhs.Release());
		return (*this);
	}

	AutoPointer<T>& operator=(AutoPointerRef<T>& rhs) throw()
	{
		Reset(rhs.ref.Release());
		return (*this);
	}

	~AutoPointer()
	{ 
		if (ptr)
			Destroy(ptr); 
	}

	T& operator*() const throw()
		{ return (*ptr); }

	T* operator->() const throw()
		{ return (&**this); }

	T* GetPointer() const throw()
		{ return (ptr); }

	T* Release() throw()
	{
		T* tmp = ptr;
		ptr = 0;
		return (tmp);
	}

	void Reset(T* p = 0)
	{
		if (ptr && p != ptr)
			Destroy(ptr);
		ptr = p;
	}

private:
	static void Destroy(T* p)
	{
		p->~T();
		Implementation::Deallocate(p);
	}

	T* ptr;
};

} // namespace KasperskyLicensing

#endif // AUTOPOINTER_H
