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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> как вызвать конструктор предка не зная кто предок? 
V
    Опции темы
mes
Дата 14.10.2010, 14:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(boostcoder @  12.10.2010,  08:11 Найти цитируемый пост)
сейчас я занимаюсь именно связыванием типов команд, с их обработчиками.

недождался я Вашего базового класса, терпеть больше не могу, выкладываю свои мысли.

У вас есть два вида типов интерфейса пакета,
  один это пользовательские данные такие как :
Код

struct login {
  std::string name;
  std::string pass;
};

ничего больше, чем нужно пользователю, тут быть не должно..

второй это оболочка над пользовательскими данными, позволяющая управлять пакетом, и желательно чтоб можно было управлять полиморфно.. 
т.е. абстрактный интерфейс например такой :
Код

struct IPacket {
   virtual ~IPacket () {}
   virtual void Accept (IDispatcher& v)  =0;
   virtual IPacket * Clone () const =0;
};

терь нам осталось только совместить первое со вторым в одном классе.. делаем шаблон :
Код

template <class T>
struct PacketAdapter : IPacket {

    PacketAdapter(T const& data ) : m_data(data) {}
     
    virtual void Accept (IDispatcher& v);
    virtual PacketAdapter * Clone () const  { return new PacketAdapter(*this); }
    
    T  m_data;
};

для работы такой конструкции нужны гарантии копирования с пользовательской стороны, либо копиконструктор либо соответсвие клонейбл идиологии..

ну и для передачи по сети  нам нужен ид. Получать мы его можем автоматом на основе списка типов:
Код

template <class T, class TypeList> 
struct PacketAdapter 
{
      enum { id = Loki::IndexOf<TypeList, T>::value };

      virtual void Accept (IDispatcher& v) { v.Dispatch(id, static_cast<void const *>(&m_data)); }

//  ...
};

ну и естественно перед использованием списков типов нужно избавиться в нем от дубликатов(на всякий случай)

P.S. чему равен аналог Loki::IndexOf<> в бусте не знаю, но если его нету, то и самому написать не сложно.. 

Это сообщение отредактировал(а) mes - 14.10.2010, 14:53


--------------------
PM MAIL WWW   Вверх
boostcoder
Дата 14.10.2010, 15:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


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

Репутация: 49
Всего: 110



mes, большое спасибо smile
я не в коем случае не забил на задачу, т.к. она мне как воздух важна. но приходится еще и другими проектами заниматься.
естественно, все эти дни я не дурью маялся, и тоже кое-что накодил smile 

сейчас, мой метагенератор, умеет генерить абстрактный класс для айпишек предоставляемых юзеру.
т.е.
этот код:
Код

DECLARE_HANDLER_CLASS(
   registration_api,
   // check if user with this nick and email already exists
   ((user_exists,
      ((query,
        ((std::string, nick))
        ((std::string, email))
      ))
      ((result,
         ((int, code))
         ((std::string, message))
      ))
   ))
   // registration query
   ((registration,
      ((query,
         ((std::string, nick))
         ((std::string, email))
      ))
      ((result,
         ((std::string, message))
         ((int, code))
      ))
   ))
   // activation query
   ((activation,
      ((query,
         ((std::string, nick))
         ((std::string, code))
      ))
      ((result,
         ((std::string, message))
         ((int, code))
      ))
   ))
)



сгенерит это:
Код

struct user_exists_query {
   user_exists_query() {}
   user_exists_query(const user_exists_query& o):nick(o.nick), email(o.email) {}
   user_exists_query(const std::string& a0, const std::string& a1 ):nick(a0), email(a1) {}

   static const int meta_id;
   static const char* meta_name;
   static const int meta_fcount;
   static const char* meta_fields[];

   std::string nick;
   std::string email;

private:
   friend class boost::serialization::access;
   template<typename archive_type>
   void serialize(archive_type& ar, const unsigned int) {
      ar & boost::serialization::make_nvp("nick", nick)
         & boost::serialization::make_nvp("email", email) ;
   }
};
const int user_exists_query::meta_id = 0 + 0;
const char* user_exists_query::meta_name = "user_exists_query";
const int user_exists_query::meta_fcount = 2;
const char* user_exists_query::meta_fields[] = {"nick", "email"};

struct user_exists_result {
   user_exists_result() {}
   user_exists_result(const user_exists_result& o):code(o.code), message(o.message) {}
   user_exists_result(const int& a0, const std::string& a1 ):code(a0), message(a1) {}

   static const int meta_id;
   static const char* meta_name;
   static const int meta_fcount;
   static const char* meta_fields[];

   int code;
   std::string message;

private:
   friend class boost::serialization::access;
   template<typename archive_type>
   void serialize(archive_type& ar, const unsigned int) {
      ar & boost::serialization::make_nvp("code", code)
         & boost::serialization::make_nvp("message", message);
   }
};
const int user_exists_result::meta_id = 0 + 0;
const char* user_exists_result::meta_name = "user_exists_result";
const int user_exists_result::meta_fcount = 2;
const char* user_exists_result::meta_fields[] = {"code", "message"};

struct user_exists: command_impl<user_exists_query,user_exists_result> {
   typedef boost::shared_ptr<user_exists> result_type;
   user_exists(const user_exists_query& q, boost::asio::ip::tcp::socket& s)
      :command_impl<user_exists_query,user_exists_result>(q, s)
   {}

   static const int meta_id;
   static const char* meta_name;

   const int& code() const {return _result.code;}
   const std::string& message() const {return _result.message;}
};
const int user_exists::meta_id = user_exists::query::meta_id;
const char* user_exists::meta_name = "user_exists";

struct registration_query {
   registration_query() {}
   registration_query(const registration_query& o):nick(o.nick), email(o.email) {}
   registration_query(const std::string& a0, const std::string& a1 ):nick(a0), email(a1) {}

   static const int meta_id;
   static const char* meta_name;
   static const int meta_fcount;
   static const char* meta_fields[];

   std::string nick;
   std::string email;

private:
   friend class boost::serialization::access;
   template<typename archive_type>
   void serialize(archive_type& ar, const unsigned int) {
      ar & boost::serialization::make_nvp("nick", nick)
         & boost::serialization::make_nvp("email", email) ;
   }
};
const int registration_query::meta_id = 1 + 0;
const char* registration_query::meta_name = "registration_query";
const int registration_query::meta_fcount = 2;
const char* registration_query::meta_fields[] = {"nick", "email"};

struct registration_result {
   registration_result() {}
   registration_result(const registration_result& o):message(o.message), code(o.code) {}
   registration_result(const std::string& a0, const int& a1 ):message(a0), code(a1) {}

   static const int meta_id;
   static const char* meta_name;
   static const int meta_fcount;
   static const char* meta_fields[];

   std::string message;
   int code;

private:
   friend class boost::serialization::access;
   template<typename archive_type>
   void serialize(archive_type& ar, const unsigned int) {
      ar & boost::serialization::make_nvp("message", message)
         & boost::serialization::make_nvp("code", code) ;
   }
};
const int registration_result::meta_id = 1 + 0;
const char* registration_result::meta_name = "registration_result";
const int registration_result::meta_fcount = 2;
const char* registration_result::meta_fields[] = {"message", "code"};

struct registration: command_impl<registration_query,registration_result> {
   typedef boost::shared_ptr<registration> result_type;
   registration(const registration_query& q, boost::asio::ip::tcp::socket& s)
      :command_impl<registration_query,registration_result>(q, s)
   {}

   static const int meta_id;
   static const char* meta_name;
   const std::string& message() const {return _result.message;}
   const int& code() const {return _result.code;}
};
const int registration::meta_id = registration::query::meta_id;
const char* registration::meta_name = "registration";

struct activation_query {
   activation_query() {}
   activation_query(const activation_query& o):nick(o.nick), code(o.code) {}
   activation_query(const std::string& a0, const std::string& a1 ):nick(a0), code(a1) {}

   static const int meta_id;
   static const char* meta_name;
   static const int meta_fcount;
   static const char* meta_fields[];

   std::string nick;
   std::string code;

private:
   friend class boost::serialization::access;
   template<typename archive_type>
   void serialize(archive_type& ar, const unsigned int) {
      ar & boost::serialization::make_nvp("nick", nick)
         & boost::serialization::make_nvp("code", code) ;
   }
};
const int activation_query::meta_id = 2 + 0;
const char* activation_query::meta_name = "activation_query";
const int activation_query::meta_fcount = 2;
const char* activation_query::meta_fields[] = {"nick", "code"};

struct activation_result {
   activation_result() {}
   activation_result(const activation_result& o):message(o.message), code(o.code) {}
   activation_result(const std::string& a0, const int& a1 ):message(a0), code(a1) {}

   static const int meta_id;
   static const char* meta_name;
   static const int meta_fcount;
   static const char* meta_fields[];

   std::string message;
   int code;

private:
   friend class boost::serialization::access;
   template<typename archive_type>
   void serialize(archive_type& ar, const unsigned int) {
      ar & boost::serialization::make_nvp("message", message)
         & boost::serialization::make_nvp("code", code) ;
   }
};
const int activation_result::meta_id = 2 + 0;
const char* activation_result::meta_name = "activation_result";
const int activation_result::meta_fcount = 2;
const char* activation_result::meta_fields[] = {"message", "code"};

struct activation: command_impl<activation_query,activation_result> {
   typedef boost::shared_ptr<activation> result_type;
   activation(const activation_query& q, boost::asio::ip::tcp::socket& s)
      :command_impl<activation_query,activation_result>(q, s)
   {}

   static const int meta_id;
   static const char* meta_name;
   const std::string& message() const {return _result.message;}
   const int& code() const {return _result.code;}
};
const int activation::meta_id = activation::query::meta_id;
const char* activation::meta_name = "activation";

struct registration_api: base_ ... {
   virtual void user_exists_handler ( user_exists_result& result, const user_exists_query& query ) = 0;
   virtual void registration_handler ( registration_result& result, const registration_query& query ) = 0;
   virtual void activation_handler ( activation_result& result, const activation_query& query ) = 0;
};

как вы можете заметить, теперь метагенератор умеет генерить настоящие структуры вместо обертки над тьюплами.

класс registration_api - базовый для реализации методов-обработчиков соответствующих типов.
т.е. юзер должен от него унаследоваться и реализовать их.

на стороне сервера используется так:
Код

struct registration_api_impl: registration_api {
   virtual void user_exists_handler ( user_exists_result& result, const user_exists_query& query ) {
      ...
   }
   virtual void registration_handler ( registration_result& result, const registration_query& query ) {
      ...
   }
   virtual void activation_handler ( activation_result& result, const activation_query& query ) {
      ...
   }
};

server<registration_api_impl> server(...);

вот smile

зы
может попросить модераторов чтоб перенести в первоначальную тему?
PM WWW   Вверх
boostcoder
Дата 14.10.2010, 15:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


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

Репутация: 49
Всего: 110



Цитата(mes @  14.10.2010,  14:50 Найти цитируемый пост)
ну и для передачи по сети  нам нужен ид.

этим занимается метагенератор. правда сейчас он генерит один ID для запроса и ответа, т.к. они являются одним целым.
PM WWW   Вверх
mes
Дата 14.10.2010, 17:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(boostcoder @  14.10.2010,  14:19 Найти цитируемый пост)
как вы можете заметить, теперь метагенератор умеет генерить настоящие структуры вместо обертки над тьюплами.

 smile 
было б хорошо добавить еще и раздельную кодогенерацию.. отдельно структуры, мета-описания и мета-определения..


Цитата(boostcoder @  14.10.2010,  14:19 Найти цитируемый пост)
на стороне сервера используется так:

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

и... если у Вас
Цитата(boostcoder @  14.10.2010,  14:19 Найти цитируемый пост)
server<registration_api_impl> server(...);

то зачем нужен абстрактный класс ? имена и так связаны, 
а заставлять пользователя без надобности использовать виртуальность не очень прилично.. 
smile

Добавлено @ 17:38
Цитата(boostcoder @  14.10.2010,  14:56 Найти цитируемый пост)
этим занимается метагенератор. правда сейчас он генерит один ID для запроса и ответа, т.к. они являются одним целым. 

с ид отдельная история.. с одной стороны делать их абсолютно автоматическими, как показано в моем примере, тоже не годится,
но и жестко привязываться в пользовательском коде, тоже не хорошо.. Лучшим вариантом было бы разгрузить через посредника, который бы по типу выдавал нужный ид. Тогда можно выбирать стратегию определения id..  Но их пока оставим на потом.. 
smile




Это сообщение отредактировал(а) mes - 14.10.2010, 17:42


--------------------
PM MAIL WWW   Вверх
boostcoder
Дата 14.10.2010, 17:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


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

Репутация: 49
Всего: 110



Цитата(mes @  14.10.2010,  17:27 Найти цитируемый пост)
отдельно структуры, мета-описания и мета-определения..

эм... поясните...

Цитата(mes @  14.10.2010,  17:27 Найти цитируемый пост)
тогда уж сделайте возможность деления на группы..

так и задумано. хочу в будущем реализовать динамическое связывание объектов по запросу клиента.
т.е.:
Код

client client(...);
client::iface_ptr regapi = client.create<registration_api>();
regapi.user_exists(...);
...
client::iface_ptr statapi = client.create<status_api>();
statapi.get_statistic(...);


Цитата(mes @  14.10.2010,  17:27 Найти цитируемый пост)
и... если у Вас
Цитата(boostcoder @  14.10.2010,  14:19 )
server<registration_api_impl> server(...);

то зачем нужен абстрактный класс ? имена и так связаны, 
а заставлять пользователя без надобности использовать виртуальность не очень прилично.. 

это переходная версия smile 
далее такого не будет.

Цитата(mes @  14.10.2010,  17:27 Найти цитируемый пост)
Но их пока оставим на потом.. 

угу.


Это сообщение отредактировал(а) boostcoder - 14.10.2010, 17:53
PM WWW   Вверх
mes
Дата 14.10.2010, 17:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(boostcoder @  14.10.2010,  16:53 Найти цитируемый пост)
client::iface_ptr regapi...  

наскoлько я понимаю тут не хватает <registration_api>

a также  заметен сдвиг в сторону асинхроности..  smile

Добавлено @ 18:01
Цитата(boostcoder @  14.10.2010,  16:53 Найти цитируемый пост)
отдельно структуры, мета-описания и мета-определения..

эм... поясните...

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


т.е придется разделить один макрос на три, но как то так, чтоб не пришлось трижды набирать структуру..
т.е. грубо говоря вначале дефайнить описание, а после подвергать различным кодогенерациям в нужном месте.. 
P.S. через #define может и не получится, а через #include вполне.. хотя первое удобнее..


Цитата(boostcoder @  14.10.2010,  16:53 Найти цитируемый пост)
так и задумано. 

 smile

Цитата(boostcoder @  14.10.2010,  16:53 Найти цитируемый пост)
это переходная версия  
далее такого не будет.

 smile 

Это сообщение отредактировал(а) mes - 14.10.2010, 18:05


--------------------
PM MAIL WWW   Вверх
boostcoder
Дата 14.10.2010, 18:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


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

Репутация: 49
Всего: 110



Цитата(mes @  14.10.2010,  17:59 Найти цитируемый пост)
наскoлько я понимаю тут не хватает <registration_api>

ааа, ну да smile 

Цитата(mes @  14.10.2010,  17:59 Найти цитируемый пост)
хотелось бы иметь все определения констант в отдельном .cpp файле
а также метуинформацию (при этом возможно собранную в структуру, для удбобного пользования) в отдельном  .h


т.е придется разделить один макрос на три, но как то так, чтоб не пришлось трижды набирать структуру..
т.е. грубо говоря вначале дефайнить описание, а после подвергать различным кодогенерациям в нужном месте.. 
P.S. через #define может и не получится, а через #include вполне.. хотя первое удобнее..

да-да. конечно. иначе сейчас в одном хидере вся кодогенерация. там черт ногу сломет smile 
PM WWW   Вверх
mes
Дата 14.10.2010, 18:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(boostcoder @  14.10.2010,  17:34 Найти цитируемый пост)
там черт ногу сломет


дело не только в ноге.. сейчас каждое включение хидера будет генерить константы..
т.е. в каждом юните будут свои копии - что не очень..ммм.. культурно...  smile 


Это сообщение отредактировал(а) mes - 14.10.2010, 18:42


--------------------
PM MAIL WWW   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
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.0852 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


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

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