/*
	Auto-Ptr-3
*/

#if !defined( _AUTO_PTR_3__INITIALIZED_PTR_HPP_ )
#define _AUTO_PTR_3__INITIALIZED_PTR_HPP_

namespace auto_ptr_3 {

//
// initialized_ptr_t
//

//!	Класс для хранения проинициализированого указателя на объект.
/*!
	Данный класс предназначен для облегчения работы с
	переменными/атрибутами - указателями. Проблема возникает, если
	переменная/атрибут объявляется, но не инициализируется.

	\par
	Особенно трудноуловима подобная проблема в классах с
	несколькими конструкторами. При добавлении конструктора и/или
	атрибута легко забыть проинициализировать атрибут-указатель.

	\par
	Класс \c initialized_ptr_t является хранилищем указателя с
	принудительной инициализацией указателя в конструкторе.

	\attention Класс \c initialized_ptr_t не уничтожает объект,
	на который указывает контролируемый указатель в своем
	деструкторе!
*/
template< class T >
class	initialized_ptr_t
{
	private :
		//! Контролируемый указатель.
		T *	m_p;

		typedef T * ptr_t;

	public :
		//! Конструктор по умолчанию присваивает 0.
		initialized_ptr_t() : m_p( 0 ) {}
		//! Конструктор с явным указанием значения.
		initialized_ptr_t( T * p ) : m_p( p ) {}

		//! Получить доступ к контролируемому указателю.
		T *
		query()
		{
			return m_p;
		}

		//! Получить доступ к контролируемому указателю.
		const T *
		query() const
		{
			return m_p;
		}

		//! Установить контролируемый указатель.
		void
		set( T * p )
		{
			m_p = p;
		}

		//! Быстрый доступ к контролируемому указателю.
		operator ptr_t() const
		{
			return m_p;
		}

		//! Получить доступ к объекту по контролируемому указателю.
		/*! \attention Результат не определен, если контролируемый
			указатель равен 0.
		*/
		T &
		operator*()
		{
			return *m_p;
		}

		//! Получить доступ к объекту по контролируемому указателю.
		/*! \attention Результат не определен, если контролируемый
			указатель равен 0.
		*/
		const T &
		operator*() const
		{
			return *m_p;
		}

		//! Получить доступ к контролируемому указателю.
		T *
		operator->()
		{
			return m_p;
		}

		//! Получить доступ к контролируемому указателю.
		const T *
		operator->() const
		{
			return m_p;
		}
};

}

#endif

