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; };
В виде TLV эти сообщения могут быть представлены в следующем виде:
user-req-tlv rid-tlv user-name-tlv req-body-tlv user-reply-tlv rid-tlv user-name-tlv result-tlv
Т.е. rid и user-name представляются одними и теми же TLV как в user-req-tlv, так и в user-reply-tlv.
При тривиальном программировании TLV-объектов был бы получен следующий код:
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 ); } ... };
Проблема заключается в том, что поля 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. Тогда в исходном тексте окажется много мест, в которые нужно внести изменения. А это повышает вероятность появления ошибок.
// Тип для 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 ); } ... };