2013-06-14 3 views
2

Я должен реализовать связь протокола с портом последовательного порта устройства. Протокол основан на двоичном выражении, где у нас есть заголовок, который содержит вид и длину пакета, необязательный элемент и контрольную сумму.о decltype в C++

Я использую C++ 11 с Visual C++ 2012 с набором инструментов v110_xp.

Моя первая попытка реализовать его, используя следующий класс:

PacketOutA, PacketOutB, PacketOutC являются все классы с общим интерфейсом, у них есть только два метода: begin() и end() для доступа к внутренней информации;

У меня есть интерфейс для ответа пакета IPacketIn, производного класса PacketIn Орудия общего персонала и дериватов PacketInA, PacketInB и так далее.

Класс Communication используется для отправки и получения данных в порт связи.

Класс ReaderAndValidator позволяет мне проверить полученный пакет и получить его.

Dispatcher<T> используется для получения входного пакета corrisponding от requestç

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

Давайте посмотрим фрагмент кода:

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 

Класс 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; 
}; 

Но я проблема с полученным методом: как я могу вывести тип возврата в этой ситуации?

Этот дизайн является хорошим выбором? Лучший способ сделать то же самое?

ответ

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)) 
//    ^^^^^^^^^^^^ 
{ 
    // ... 
} 
+0

Wow это Ответ на пост, который я когда-либо видел. Теперь он компилирует спасибо. –

+0

Как вы думаете, это плохой дизайн? Или это приемлемо? –

+0

@ elvis.dukaj: Да, я думаю, это приемлемо. Конечно, есть альтернативы, но этот выбор выглядит хорошо для меня. –

Смежные вопросы