
This looks like a perfect place for Boost.Variant. Here is some pseudo code: #include <boost/variant.hpp> struct DecoderVisitor: boost ::static_vizitor<> { istream& Stream; explicit DecoderVisitor(istream& Stream): Stream(Stream){} void operator()(String& s) const { s.Decode(Stream); } void operator()(Double& d) const { d.Decode(Stream); } // or you may just write // template <class T> // void operator()(T& val) const { // val.Decode(Stream); //} }; class EmployeePacket { typedef boost::variant<String, Double> variant_t; std::vector<variant_t> Items; EmployeePacket() { Items.push_back(String("name", "John Doe")); Items.push_back(Double("salary", "USD", 1, 1)); } void Decode(istream& Stream) { for (auto pItem : Items) boost::apply_visitor(DecoderVisitor(Stream), pItem) } double GetSalary() { return boost::get<Double>(Items[1]).value; } } class Double { string name; string units; // double decode_conversion_scale; // double decode_conversion_translate; // unsigned number_of_bits_used_to_encode // double scale_factor double value; void Decode(istream& Stream) { Stream.read(&value, 8); value = value * decode_conversion_scale + decode_conversion_translate; } class String { string name; string value; void Decode(istream& Stream); } Advantages are: * less calls to new => faster code * no raw pointers => much safer * no virtual functions and dynamic casts => much faster and safer * you exactly specify which types will be stored in variant => more compile time checks And Boost.Variants documentation is not big and it is a simple enough library. -- Best regards, Antony Polukhin