I want a good design to implement a master-slave protocol. The protocol is proprietary and similar to cctalk.We have:Master: HEADER [ DATA ] CHECKSUMSlave: HEADER [ DATA ] CHECKSUMMy choice was to have concrete base classes for request and for response:class PacketReq {public:    typedef std::vector<uint8_t>       container;    typedef container::const_iterator  const_iterator;    PacketCommand command() const    {        return static_cast< PacketCommand >( mBuffer[ 2 ] );    };    const container& data() const    {        return mBuffer;    }    const_iterator begin() const    {        return mBuffer.begin();    }    const_iterator end() const    {        return mBuffer.end();    }protected:    container mBuffer;};class PacketOut1 : public PacketReq {public:    PacketOut1()    {        mBuffer.reserve( PacketHeaderHelper::HEADER_SIZE );        mBuffer.push_back( /* something. */ );        mBuffer.push_back( /* something. */ );        mBuffer.push_back( /* something. */ );        mBuffer.push_back( /* something. */ );    }};The response can be a good response or a NACK (an error). My Implentation is:class PacketRes {public:    PacketRes(const std::vector<uint8_t>& buffer)     {        if (!checkChecksum( buffer ))        {            throw Error(invalid checksum);        }        PacketHeaderHelper header( buffer );        mCommand = header.command();        if (header.len() > PacketHeaderHelper::HEADER_SIZE)        {            const size_t bodySize = header.len() - PacketHeaderHelper::HEADER_SIZE;            mData.reserve( bodySize );            mData.insert(                mData.end(),                buffer.begin() + PacketHeaderHelper::HEADER_SIZE - 1,                buffer.end() - 1                );        }            }    virtual ~PacketReq() {}    PacketCommand command() const    {        return mCommand;    }        const std::vector<uint8_t>& body() const    {        return mData;    }private:    bool checkChecksum(const std::vector<uint8_t>& buffer) const    {        /* calc checksum. */    }private:    std::vector<uint8_t> mData;    PacketCommand mCommand;};class PacketInAck : public PacketReq {public:    PacketInAck(const std::vector<uint8_t>& buffer) : PacketReq( buffer )    {    }};So if I want make a request the sequence is:lock_guard send( const PacketOut& p ) std::unique_ptr< PacketRes > read();But I don't like this design, but it works.Is there some other way to implement this?
Design for a protocol based software in C++
c++;design patterns
A possible altenrative implementation can be the following:All the packet have no inheritance, nor recieved packet nor sent packetPacketOutA, PacketOutB, PacketOutC are all classes with a common interface, they have just two method: begin() and end() to access internal data;The recieved class are PacketInA, PacketInB and so on.The class Communication is used to allow me to send and recieve data to the communication port.The ReaderAndValidator class allow me to get and validate the body of the recieved packet.The Dispatcher class allow me to obtain a packet from a recieved one ( sorry for my english... look the example... )The Device class instead is needed to rappresent, in a domain context, our connected device./** abstract the communication mechanism. */class Communication {public:    Communication ();    template < typename Iterator >    void send( Iterator first, Iterator last ) const    {        // send from first to last to     }    template< typename Iterator >    std::vector< char > read( Iterator first, Iterator last ) const    {        // read from first to last to     }private:    // internal stuff};/** Validate an input packet and get the body */class ReaderAndValidator {public:    ReaderAndValidator ( const Communication& comm )        : mComm( comm )    {    }    std::vector< char > read()    {        // read data        return mComm.read( /* params */ );    }private:    const Communication& mComm;}/** Given the PacketOut obtain the corrisponding PacketIn. */template < typename PacketOut >class Dispatcher {    Dispatcher()    {        static_assert( false, unable to instantiate Controller );    }};template <>class Dispatcher< PacketOutA > {public:    Dispatcher( const Communication& comm )        : mComm( comm )    {    }    PacketInA send( const PacketOutA & packet ) const    {        mComm.send( std::begin( packet ), std::end( packet ) );        ReaderAndValidator reader( mComm );        auto body = reader.read();        // RVO        PacketInA result( std::begin( body ), std::end( body ) );        return result;    }private:    const Communication& mComm;};// same thing for Controller< PacketOutB >, Controller< PacketOutC > and so onclass Device : private boost::noncopyable {public:    Device ()    {        // init communication    }    void doPacketOutA( int param )    {        PacketOutA packet( param );        recieve( packet );    }    PacketInB doPacketB()    {        PacketOutB packet();        return recieve( packet );    }private:    template < typename PacketOutKind >    auto recieve( const PacketOutKind& p ) -> decltype( std::declval< Dispatcher< PacketOutKind > >().send( p ) ) )    {        Dispatcher< PacketOutKind > disp( mCommunication );        return controller.send( p );    }private:    Communication mCommunication;};