2

I've to implement a protocol communication with a device throw serial port. The protocol is binary based where we have an header that containt the kind and the length of the packet, an optional body and a checksum.

I'm using C++11 with Visual C++ 2012 with the v110_xp toolset.

My first attempt to implement it is using the following class:

PacketOutA, PacketOutB, PacketOutC are all classes with a common interface, they have just two method: begin() and end() to access internal data;

I have an interface for response packet IPacketIn, a derived class PacketIn the implement common staff and the derivates 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 validate the recieved packet and get the body.

Dispatcher< T > is used to get the corrisponding input packet from the requestç

PacketInA doPacketA()
{
    PacketA packetA;
    Dispatcher< PacketA > disp( communication );
    PacketInA result = controller.send( packetA );
    return result; // RVO
}

Let's look the snippet of the code:

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
};

class ReaderAndValidator{
public:

    ReaderAndValidator( const Communication& comm )
        : mComm( comm )
    {
    }

    std::vector< char > read()
    {
        // read data
        return mComm.read( /* params */ );
    }

private:
    const Communication& mComm;
}

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 readAndValidate( mComm );
        auto body = readAndValidate.read();

        // RVO
        PacketInA result( std::begin( body ), std::end( body ) );
        return result;
    }

private:
    const Communication& mComm;
};

// same thing for Dispatcher< PacketOutB >, Dispatcher< PacketOutC > and so on

The class Device abstract the operation that I can do on my device

class 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( Dispatcher< PacketOutKind >::send( p ) )
    {
        Dispatcher< PacketOutKind > disp( mCommunication );
        return controller.send( p );
    }

private:

    Communication mCommunication;
};

But I have a problem with the recieved method: how can I deduce the return type in this situation?

Is this design a good choice? Are better way to do the same thing?

4

1 回答 1

3

send()函数不是静态的,因此您需要一个实例来调用它。

您可以使用std::declval<>()创建一个虚拟实例 - 它是一个未评估的上下文,并且declval()只是转换为引用类型,因此该类不会真正被实例化:

#include <utility>

template < typename PacketOutKind >
    auto receive( const PacketOutKind& p ) -> 
//          ^^
//          Totally unrelated spelling issue :)
        decltype( std::declval< Controller< PacketOutKind > >().send( p ) )
//                ^^^^^^^^^^^^
{
    // ...
}
于 2013-06-14T14:06:32.500 回答