Re: Архитектура сетевого приложения
От: vic.scherba  
Дата: 08.04.14 21:27
Оценка:
Здравствуйте!

Подниму старую тему. Случайно нагуглил по ключевому слову "мультиметоды". Позвольте попиариться.
Ваша задача решается очень просто с помощью мультиметода.
Пример упростил для понимания и чтобы скомпилировать и проверить.

#include <iostream>
#include <functional>

#include <mml/generation/make_multimethod.hpp>


struct BasePacket
{
   virtual void F() const = 0; // большой список параметров
};

struct PingPacket: public BasePacket
{   
   virtual void F() const
   {
   }

   int int_field;
};

struct PongPacket: public BasePacket
{
   virtual void F() const // лишние параметры
   {
   }

   float float_field;
};

struct Connection
{
    void handle_packet_base(BasePacket *packet)
    {
        std::cout << typeid(BasePacket).name();
    }

    void handle_packet_ping(PingPacket *packet)
    {
        std::cout << typeid(PingPacket).name();
    }

    void handle_packet_pong(PongPacket *packet)
    {
        std::cout << typeid(PongPacket).name();
    }

    void main_cycle()
    {
        // p может указывать на любой объект подкласса BasePacket или самого BasePacket
        BasePacket *p = new PingPacket; // receive_packet()

        mml::make_multimethod(
              std::mem_fun(&Connection::handle_packet_base)
            , std::mem_fun(&Connection::handle_packet_ping)
            , std::mem_fun(&Connection::handle_packet_pong)
            ) // создает функциональный объект
        (this, p); // вызывает его

        // если доступно ключевое слово auto, то можно сохранить мультиметод в переменную auto mm = make_multimethod(...),
        // иначе, можно сохранить, обернув в boost::function<void(Connection*, BasePacket*)> mm = make_multimethod(...),
        // или передать в шаблонную функцию, которая сама выведет тип мультиметода
        // как своего шаблонного параметра, например: process_packet(make_multimethod(...), this, p)
    }
};


Единственное, что здесь важно — это создать мультиметод.
Для этого нужно заинклудить: <mml/generation/make_multimethod.hpp> и вызвать mml::make_multimethod.

Хотя в этом примере мультиметод вырожденный (он диспетчеризует по одному полиморфному аргументу, а не по множеству), тем не менее его можно использовать как внешнюю полиморфную функцию над одним аргументом (connection здесь не полиморфен и в диспетчеризации не участвует).
В этой библиотеке можно смешивать полиморфные и неполиморфные аргументы. Диспетчеризация в рантайме будет работать только на полиморфных аргументах (будет вычисляться их реальный динамический подтип).

Библиотека находится тут.
Описание с примерами и теорией можно почитать тут.
Надеюсь, библиотека будет полезна.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.