/*!

\page	tlv_tagged_scalar_wrapper	Обертка вокруг TLV-скаляров

Опыт применения первой реализации классов oess_1::tlv::scalar_tlv_t
и oess_1::tlv::basic_string_tlv_t в виде элементов составного TLV
(oess_1::tlv::compound_tlv_t) привел к появлению класса
oess_1::tlv::tagged_scalar_wrapper_t. Ниже описываются причины
его появления и то, как этот класс может упростить программирование
составных TLV.

\section tlv_tagged_scalar_wrapper__problem Проблема

Предположим, что требуется представить в TLV запрос user_req и
ответ на запрос user_reply, которые описываются следующими C++
структурами:

\code
struct	user_req_t
{
	// Идентификатор запроса.
	unsigned int	m_rid;
	// Имя пользователя.
	std::string	m_user_name;
	// Текст запроса.
	std::string	m_req_body;
};

struct	user_reply_t
{
	// Идентификатор запроса.
	unsigned int	m_rid;
	// Имя пользователя.
	std::string	m_user_name;
	// Результат обработки.
	unsigned int	m_result;
};
\endcode

В виде TLV эти сообщения могут быть представлены в следующем виде:

\verbatim
user-req-tlv
	rid-tlv
	user-name-tlv
	req-body-tlv

user-reply-tlv
	rid-tlv
	user-name-tlv
	result-tlv
\endverbatim

Т.е. rid и user-name представляются одними и теми же TLV как в
user-req-tlv, так и в user-reply-tlv.

При тривиальном программировании TLV-объектов был бы получен
следующий код:

\code
class	user_req_tlv_t :
	public oess_1::tlv::compound_tlv_t
{
	typedef oess_1::tlv::compound_tlv_t base_type_t;

	private :
		// Для rid-tlv.
		oess_1::tlv::scalar_tlv_t< oess_1::uint_t, oess_1::uint_t >
			m_rid_tlv;
		// Для user-name-tlv.
		oess_1::tlv::basic_string_tlv_t< oess_1::uint_t >
			m_user_name_tlv;
		// Для req-body-tlv.
		oess_1::tlv::basic_string_tlv_t< oess_1::uint_t >
			m_req_body_tlv;
	public :
		user_req_tlv_t()
			:
				base_type_t( c_user_req_tag ),
				m_rid_tlv( c_rid_tag ),
				m_user_name_tlv( c_user_name_tag ),
				m_req_body_tlv( c_req_body_tag )
		{
			tlv_add( m_rid_tlv );
			tlv_add( m_user_name_tlv );
			tlv_add( m_req_body_tlv );
		}
		...
};

class	user_reply_tlv_t :
	public oess_1::tlv::compound_tlv_t
{
	typedef oess_1::tlv::compound_tlv_t base_type_t;

	private :
		// Для rid-tlv.
		oess_1::tlv::scalar_tlv_t< oess_1::uint_t, oess_1::uint_t >
			m_rid_tlv;
		// Для user-name-tlv.
		oess_1::tlv::basic_string_tlv_t< oess_1::uint_t >
			m_user_name_tlv;
		// Для result-tlv.
		oess_1::tlv::scalar_tlv_t< oess_1::uint_t, oess_1::uint_t >
			m_result_tlv;
	public :
		user_reply_tlv_t()
			:
				base_type_t( c_user_reply_tag ),
				m_rid_tlv( c_rid_tag ),
				m_user_name_tlv( c_user_name_tag ),
				m_result_tlv( c_result_tag )
		{
			tlv_add( m_rid_tlv );
			tlv_add( m_user_name_tlv );
			tlv_add( m_result_tlv );
		}
		...
};
\endcode

Проблема заключается в том, что поля m_rid_tlv и m_user_name_tlv
должны связываться с константами c_rid_tag, c_user_name_tag в
каждом (!) конструкторе классов user_req_tlv_t и user_reply_tlv_t.
В нормальном варианте, в каждом из классов должно быть три
конструктора: по умолчанию, со всеми параметрами и копирования.
Т.е. в нормальном варианте классов user_req_tlv_t и user_reply_tlv_t
придется указывать константы c_rid_tag и c_user_name_tag 6 раз!
Хуже всего, что короме затрат времени на написание вызовов
конструкторов m_rid_tlv и m_user_name_tlv, в дальнейшем может
потребоваться заменить для какого-то поля значение Tag. Тогда
в исходном тексте окажется много мест, в которые нужно внести
изменения. А это повышает вероятность появления ошибок.

\section tlv_tagged_scalar_wrapper__solution Решение

Решение состоит в том, что посредством класса
oess_1::tlv::tagged_scalar_wrapper_t описывается тип, связывающий
конкретный Tag с типом обработчика скалярного Value:

\code
// Тип для rid-tlv.
typedef oess_1::tlv::tagged_scalar_wrapper_t<
		c_rid_tag,
		oess_1::tlv::scalar_tlv_t< oess_1::uint_t, oess_1::uint_t > >
	rid_tlv_t;

// Тип для user-name-tlv.
typedef oess_1::tlv::tagged_scalar_wrapper_t<
		c_user_name_tag,
		oess_1::tlv::basic_string_tlv_t< oess_1::uint_t > >
	user_name_tlv_t;

// Тип для req-body-tlv.
typedef oess_1::tlv::tagged_scalar_wrapper_t<
		c_req_body_tag,
		oess_1::tlv::basic_string_tlv_t< oess_1::uint_t > >
	req_body_tlv_t;

// Тип для result-tlv.
typedef oess_1::tlv::tagged_scalar_wrapper_t<
		c_result_tag,
		oess_1::tlv::scalar_tlv_t< oess_1::uint_t, oess_1::uint_t > >
	result_tlv_t;

class	user_req_tlv_t :
	public oess_1::tlv::compound_tlv_t
{
	typedef oess_1::tlv::compound_tlv_t base_type_t;

	private :
		// Для rid-tlv.
		rid_tlv_t	m_rid_tlv;
		// Для user-name-tlv.
		user_name_tlv_t	m_user_name_tlv;
		// Для req-body-tlv.
		req_body_tlv_t	m_req_body_tlv;
	public :
		user_req_tlv_t()
			:
				base_type_t( c_user_req_tag )
		{
			tlv_add( m_rid_tlv );
			tlv_add( m_user_name_tlv );
			tlv_add( m_req_body_tlv );
		}
		...
};

class	user_reply_tlv_t :
	public oess_1::tlv::compound_tlv_t
{
	typedef oess_1::tlv::compound_tlv_t base_type_t;

	private :
		// Для rid-tlv.
		rid_tlv_t	m_rid_tlv;
		// Для user-name-tlv.
		user_name_tlv_t	m_user_name_tlv;
		// Для result-tlv.
		result_tlv_t	m_result_tlv;
	public :
		user_reply_tlv_t()
			:
				base_type_t( c_user_reply_tag )
		{
			tlv_add( m_rid_tlv );
			tlv_add( m_user_name_tlv );
			tlv_add( m_result_tlv );
		}
		...
};
\endcode
*/

