Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> runtime выбор типа 
:(
    Опции темы
GoldFinch
Дата 20.9.2009, 14:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Завсегдатай
Сообщений: 2141
Регистрация: 30.11.2008

Репутация: 15
Всего: 26



есть набор структур с данными, для каждой структуры есть код который ее обрабатывает, для этого кода есть общий "контекст" (данные) в котором он работает
каждая структура имеет свой id, допустим целое число

по сети, или из файла, приходит буфер который содержит данные какой-то структуры, и id этой структуры
надо написать код который по полученному id определит какая структура лежит в буфере и выполнит код ее обработки.
(каждая структура имеет конструктор который загружает ее из буфера)

допустим, что "контекст" - это класс, код обработки - метод этого класса, перегруженный для каждой структуры.
(все можно сделать наоборот, например код обработки- метод структуры, и ему передается контекст)
Код

struct Foo {
  static const id_t id = 1;
  Foo(buf_t& buf) {/*код загрузки из буфера buf*/}
  /*данные*/
  .........
};
struct Bar {
  static const id_t id = 2;
  Bar(buf_t& buf) {/*код загрузки из буфера buf*/}
  /*данные*/
  .........
};
struct Context
{   
  /*данные*/
  ...........

  Process( Foo & data ) {/*код обработки*/}
  Process( Bar & data ) {/*код обработки*/}
  ............
};


я пока что придумал примерно три решения

1) switch
Код

void Dispatch(Context& ctx, id_t id, buf_t& buf)
{
  switch(id)
  {
  default: assert(!"unknown id");
  Foo::id : ctx.Process( Foo(buf) );
  Bar::id : ctx.Process( Bar(buf) );
  }
}


2) саморегистрирующиеся фабрики
Код

template<class Context>
struct Register
{
    template<class Processee>
    static bool Reg()
    {
        Map()[Processee::id] = &StartProcess<Processee>;
        return true;
    }

    typedef void(*StartProcess_t)(Context& ctx, buf_t& buf);
    
    template<class Processee>
    static void StartProcess(Context& ctx, buf_t& buf)
    {
        ctx.Process( Processee(buf) );
    }

    typedef std::map<id_t,StartProcess_t> map_t;
    static map_t& Map()
    {
        static map_t map_;
        return map_;
    }
};
template<class Context>
void Dispatch(Context& ctx, id_t id, buf_t& buf)
{
    Register<Context>::map_t map_=Register<Context>::Map();
    assert( map_.find(id) != map_.end() && "unknown id" );
    (map_[id])(ctx,buf);
}

#define REGISTER(name)  \
    struct Context;     \
    struct name;        \
    namespace trash{ bool BOOST_PP_CAT(reg,__LINE__) = Register<Context>::Reg<name>(); } \
    struct name         \
    /*******************/

REGISTER(Foo)
{
    static const int id = 1;
    Foo(buf_t){/*...*/}    
    /*...*/
};

REGISTER(Bar)
{
    static const int id = 2;
    Bar(buf_t){/*...*/}
    /*...*/
};

в этом варианте добавлять новые структуры удобно, все сосредоточенно в одном месте

3) списки типов
Код

template<typename AccepteesList>
void Dispatch(Context& ctx, id_t id, buf_t& buf)
{
  typedef boost::mpl::front<PacketsListTail>::type current_t;
  if( current_t::id == id )
    return ctx.Process( current_t(buf) );

  Dispatch<boost::mpl::pop_front<AccepteesList>::type>(ctx,id,buf);
}
template<>
void Dispatch<boost::mpl::list<>::type>(Context&, id_t, buf_t&)
{
  assert(!"unknown id");
}

..................
/* запуск Dispatch */
Dispatch<boost::mpl::list<Foo,Bar>::type>(ctx,id,buf);


Какие еще могут быть варианты?
PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0384 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.