Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > использование тьюпл как общей сущности взамен стру


Автор: boostcoder 15.9.2010, 15:47
Всем доброго дня.
Так как все топовые производители зарелизили версии компиляторов поддерживающих c++0x, встал резонный вопрос: почему бы вместо всеобразных типов структур, не использовать тьюплы? Идея в том, чтоб не плодить сущности.
Например:
Код

struct point_t {
   int x;
   int y;
};

struct point3d_t {
   int x;
   int y;
   int z;
};

struct rect_t {
   point_t left;
   point_t right;
};

struct rect3d_t {
   point3d_t left;
   point3d_t right;
};

Что мы имеем в итоге: четыре разных типа, и четыре разных сущности.
Какие у такого способа плюсы - я не знаю. Минусы - очевидны. Обобщить алгоритмы работающие с этими типами можно, посредством шаблонов или адаптеров(переходников). Но смысл в этом какой? - я, честно говоря, не понимаю.

Представьте ситуацию, в которой, все эти типы были бы тьюплами:
Код

typedef std::tuple<int, int> point_t;
typedef std::tuple<int, int, int> point3d_t
typedef std::tuple<point_t, point_t> rect_t;
typedef std::tuple<point3d_t, point3d_t> rect3d_t;

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

Собственно, реализовать общение к членам, пытаюсь с помощью препроцессора.
Предварительный пример:
Код

DECLARE_TUPLE(point_t)
   DECLARE_MEMBER(int, x)
   DECLARE_MEMBER(int, y)
END_TUPLE()


Интересует ваше мнение.

зы
как все же правильно они называются, тьюплы или кортежи?

Автор: djamshud 15.9.2010, 16:08
>как все же правильно они называются, тьюплы или кортежи?

Кортеж - это перевод тюпла на великий и могучий. К.О.

Минусы:

 - конпеляторы топовых версий - дрянь;
 - нет совметимости с си.

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

Автор: boostcoder 15.9.2010, 16:09
Цитата(djamshud @  15.9.2010,  16:08 Найти цитируемый пост)
- конпеляторы топовых версий - дрянь;

какой из них?: gcc, msvc, edg, comeau, intel?

Автор: azesmcar 15.9.2010, 16:12
Цитата(djamshud @  15.9.2010,  16:08 Найти цитируемый пост)
Но вообще штука годная, я сам стараюсь использовать pair вместо простых структур. 

а принудительное использование first и second вместо вразумительных имен никак не смущает?

Автор: djamshud 15.9.2010, 16:18
Думаю, все. Топовая версия - это, считай, немного устаканенный транк. Багов обычно нет, а регрессий - море. Помните эпичный фэйл, когда гцц 4.5 и 4.6 не могли ничего заинлайнить? Так вот это только один из примеров. Если немного следить за выпусками гцц и сопутствующими обсуждениеми, видно, что на топе куча плюшек и куча регрессий, а потом в промежуточных версиях регрессии убирают.

Например гцц 4 в сравнении с гцц 3 был просто кошмаром и только к ветке 4.4 от регрессий начали избавляться и вообще вся ветка 4.4 - это по большей части багфикс с небольшими бэкпортами новых фич.

Автор: boostcoder 15.9.2010, 16:19
Цитата(azesmcar @  15.9.2010,  16:12 Найти цитируемый пост)
а принудительное использование first и second вместо вразумительных имен никак не смущает? 

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

Автор: djamshud 15.9.2010, 16:20
azesmcar, меня не смущает, потому что называю их key и value, а структуры такие нужны обычно только в таком качестве. Второе известное мне применение - координаты, - но тут использую struct.

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

Автор: azesmcar 15.9.2010, 16:23
Цитата(boostcoder @  15.9.2010,  16:19 Найти цитируемый пост)
да. бывают моменты когда хочется задекларировать десятку-две структур smile  

ну по моему
Код

rect r;
r.bottom = 20;
r.top = 10;
r.left = 15;
r.right = 50;

читается намного легче, чем
Код

rect r;
r.first.first = 20;
r.first.second = 10;
r.second.first = 15;
r.second.second = 50;


Добавлено через 1 минуту и 9 секунд
Цитата(djamshud @  15.9.2010,  16:20 Найти цитируемый пост)
azesmcar, меня не смущает, потому что называю их key и value, а структуры такие нужны обычно только в таком качестве. 

насколько я понял ТС спрашивал про использование тюплов всегда и везде, вместо структур, а на мой взгляд это затрудняет чтение кода.

Добавлено через 1 минуту и 21 секунду
Цитата(djamshud @  15.9.2010,  16:20 Найти цитируемый пост)
Второе известное мне применение - координаты, - но тут использую struct. 

 smile 

Автор: boostcoder 15.9.2010, 16:34
Цитата(azesmcar @  15.9.2010,  16:23 Найти цитируемый пост)
насколько я понял ТС спрашивал про использование тюплов всегда и везде, вместо структур

по большому счету - да.

Цитата(azesmcar @  15.9.2010,  16:23 Найти цитируемый пост)
а на мой взгляд это затрудняет чтение кода.

да. если использовать std::get<>() для обращения к членам.

но если свести синтаксис к:
Код

rect r;
r.bottom = 20;
r.top = 10;
r.left = 15;
r.right = 50;

то это не в счет smile 

Автор: kemiisto 15.9.2010, 16:36
Цитата(boostcoder @  15.9.2010,  16:47 Найти цитируемый пост)
как все же правильно они называются, тьюплы или кортежи?

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

Цитата(boostcoder @  15.9.2010,  16:47 Найти цитируемый пост)
Интересует ваше мнение.

У меня для Вас плохие новости. smile Вот чем, пожалуй, отличаются программисты С++, так это неуёмны желанием использовать всё и вся не по назначению. Помните, у вас в руках инструмент ещё более острый, чем та самая бритва. Ну и, конечно, первый друг "творца" в создании кровавого месива - препроцессор... Я повторяюсь...

Использовать кортежи как замену классам нужно крайне осторожно. Пожалуй, однозначно не стоит делать это в Public API. Интерпретировать трудно. Как только появилась необходимость передавать/возращать кортеж, надо начинать думать о создании класса/структуры.

Для "внутреннего применения" может пригодиться. Сценарий "навскидку":

Функция возвращает не только некоторое значение, но и булеву переменную, указывающую стоит ли использовать первое значение далее в программе. При поиске, например, такое часто бывает. Чтобы не использовать передачу параметров по ссылке/указателю. Всё-таки чистые функции предпочтительнее. А городить огород с лишней структурой тут и в правду желания нет.

Автор: boostcoder 15.9.2010, 16:41
так же, стоит вспомнить про std::tie(). что является огромным плюсом при работе с членами кортежей.

Добавлено @ 16:44
Цитата(kemiisto @  15.9.2010,  16:36 Найти цитируемый пост)
Ну и, конечно, первый друг "творца" в создании кровавого месива - препроцессор

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

Автор: bsa 15.9.2010, 18:06
Кортежи использовать вместо структур глупо. Использовать вместо координат неразумно, так как читабельность падает. Для "ключ-значение" они больше подходят, но опять же, если есть лишние 10 минут, лучше накатать специальную структурку.

На мой взгляд, они нужны исключительно для создания сложных шаблонных творений (а-ля boost::bind), когда типы и количество членов кортежа определяется в момент компиляции.

ИМХО

Автор: boostcoder 15.9.2010, 18:11
Цитата(bsa @  15.9.2010,  18:06 Найти цитируемый пост)
Кортежи использовать вместо структур глупо

ок...

Цитата(bsa @  15.9.2010,  18:06 Найти цитируемый пост)
Использовать вместо координат неразумно

координаты - это просто пример. первое, тривиальное, что в голову пришло.

Цитата(bsa @  15.9.2010,  18:06 Найти цитируемый пост)
читабельность падает

уже ответил -
Цитата(boostcoder @  15.9.2010,  16:34 Найти цитируемый пост)
но если свести синтаксис к:
rect r;
r.bottom = 20;
r.top = 10;
r.left = 15;
r.right = 50;


Цитата(bsa @  15.9.2010,  18:06 Найти цитируемый пост)
Для "ключ-значение" они больше подходят, но опять же, если есть лишние 10 минут, лучше накатать специальную структурку.

чем лучше?

Цитата(bsa @  15.9.2010,  18:06 Найти цитируемый пост)
На мой взгляд, они нужны исключительно для создания сложных шаблонных творений (а-ля boost::bind), когда типы и количество членов кортежа определяется в момент компиляции.

увы.
посмотрите на великолепное творение - http://www.boost.org/doc/libs/1_43_0/libs/fusion/doc/html/index.html. воистину великолепное smile 

Автор: azesmcar 15.9.2010, 20:26
Цитата(boostcoder @  15.9.2010,  16:34 Найти цитируемый пост)
но если свести синтаксис к:

каким образом? с помощью макросов? чем тогда тюплы от обычных структур отличаются, разве что тем, что объявляться нестандартно и опять таки затрудняют чтение. В общем я думаю так, если прибегать к каким-то нестандартным методом на то должно быть основание. Так в чем причина использования тюплов вместо структур? Что вы выигрываете? 

Автор: boostcoder 15.9.2010, 20:29
Цитата(azesmcar @  15.9.2010,  20:26 Найти цитируемый пост)
чем тогда тюплы от обычных структур отличаются

сущность одна - кортеж.

Автор: djamshud 15.9.2010, 20:30
azesmcar, кортеж - это ж по-европейски! :)

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

Автор: azesmcar 15.9.2010, 20:36
Цитата(djamshud @  15.9.2010,  20:30 Найти цитируемый пост)
azesmcar, кортеж - это ж по-европейски! smile

да уж..и не слышал такого термина smile

Автор: mes 15.9.2010, 22:28
мне кажется автору интересно не столько использование кортежей вместо структур, сколько наличие у структур возможности енумерации полей.. но мне кажется овчинка выделки не стоит..


Автор: bsa 15.9.2010, 23:48
Цитата(boostcoder @  15.9.2010,  19:11 Найти цитируемый пост)
посмотрите на великолепное творение - boost.fusion. воистину великолепное

Я пока еще не придумал, зачем мне это нужно. Возможно, конечно, что я не понял всех прелестей этой библиотеки, но идея вектора, состоящего из данных разных типов, задаваемых на этапе компиляции, кажется мне несколько надуманной. Если мне нужен контейнер для любых данных, я использую boost::any, а если Variant, то я использую свою реализацию (а не бустовскую, непонятно зачем вообще сделанную), которая поддерживает преобразование в требуемый тип (в моем случае, требуется только совместимость его с istream/ostream).

Автор: boostcoder 16.9.2010, 00:31
boost.fusion - это, преимущественно, компайл-тайм библиотека(mpl). но в отличии от boost.mpl, она помогает связывать компайл-тайм код с ран-тайм кодом, и предоставляет контейнеры и алгоритмы времени компиляции.

Цитата(bsa @  15.9.2010,  23:48 Найти цитируемый пост)
я использую boost::any

1. этим, вы теряете всю информацию о типе. и ни о каком mpl говорить неуместно.
2. зачем вам тратить процессорное время, на каст туда-обратно. при том, что в момент компиляции, компилятор многое может сделать сам, и "разгрузить" процессор от ненужного ему занятия.

Цитата(bsa @  15.9.2010,  23:48 Найти цитируемый пост)
 а если Variant, то я использую свою реализацию (а не бустовскую, непонятно зачем вообще сделанную)

variant и any - ран-тайм классы. сплошной оверхед. именно по этой причине, в последнее время, интенсивно применяется mpl.
если не секрет, чем ваша реализация лучше boost.variant? и чем не утраивает boost.variant? просто любопытно.

Добавлено @ 00:39
тема-то не об этом...

Автор: bsa 16.9.2010, 11:04
Цитата(boostcoder @  16.9.2010,  01:31 Найти цитируемый пост)
чем ваша реализация лучше boost.variant? и чем не утраивает boost.variant?

 smile У каждого класса есть сигналы/слоты. В качестве параметров они принимают разные типы (int, double, string...). Чтобы стандартизировать интерфейсы я использовал свою версию варианта. В большинстве случаев (во время работы) используется передача данных напрямую (т.е. если слот принимает int, то и отправляется ему int), но на этапе инициализации все идет через string (так как все записано в xml). Чтобы не плодить разные интерфейсы, мной было сделано именно так.

Автор: boostcoder 6.10.2010, 20:45
задача решена, проверенна, и мега удобна!
собственно приоткрою истинную цель задумки.
по роду деятельности, часто приходится работать с протоколами/создавать протоколы обмена.
что для этого нужно? :
1. куча структур.
2. куча парсеров байт-массивов.

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

решил задачу, путем написания препроцессорного метагенератора.
и так...
в нашем проекте нам потребуется файл, в котором мы будем typedef`ить наши типы. назовем его "typedefs.hpp".
Код

#ifndef TYPEDEFS_HPP_INCLUDED
#define TYPEDEFS_HPP_INCLUDED

#include "tuple_metagen_start.hpp"

/***************************************************************************/

DECLARE_TUPLES(
   ((room_t,
      ((std::string, name))
      ((std::vector<std::string>, inbound))
   ))
   ((type1,
      ((std::size_t, size))
      ((std::string, message))
   ))
   ((type2,
      ((std::string, string))
      ((std::string, code))
      ((std::string, message))
   ))
   ((type3,
      ((int, from))
      ((int, to))
      ((room_t, inbound))
   ))
)

/***************************************************************************/

#include "tuple_metagen_finish.hpp"

#endif // TYPEDEFS_HPP_INCLUDED


в результате, препроцессор сгенерирует такой код:
Код

struct room_t: boost::fusion::tuple< std::string, std::vector<std::string> > {
   room_t() {}
   room_t(const room_t& o)
      :boost::fusion::tuple< std::string, std::vector<std::string> >(o)
   {}
   room_t( const std::string & a0 , const std::vector<std::string> & a1 )
      :boost::fusion::tuple< std::string, std::vector<std::string> >( a0 , a1 )
   {}

   // вспомогательные методы
   enum { id = 0 }; // для метакода. инкрементируется метагенератором.
   static const char* name() { return "room_t"; }
   static int count() { return 2; }
   static const char** methods() {
      static const char* names[] = { "name" , "inbound" , 0 };
      return names;
   }

   // accessors
   void name (const std::string & v) { boost::fusion::get<0>(*this) = v; }
   const std::string& name () const { return boost::fusion::get<0>(*this); }
   void inbound (const std::vector<std::string> & v) { boost::fusion::get<1>(*this) = v; }
   const std::vector<std::string>& inbound () const { return boost::fusion::get<1>(*this); }

private:
   friend class boost::serialization::access;
   template<typename archive_type>
   void serialize(archive_type& ar, const unsigned int) {
      ar & boost::fusion::get<0>(*this)
         & boost::fusion::get<1>(*this) ;
   }
};

struct type1: boost::fusion::tuple< std::size_t, std::string > {
   type1() {}
   type1(const type1& o)
      :boost::fusion::tuple< std::size_t, std::string>(o)
   {}
   type1( const std::size_t & a0 , const std::string & a1 )
      :boost::fusion::tuple< std::size_t, std::string >( a0 , a1 )
   {}

   // вспомогательные методы
   enum { id = 1 }; // для метакода. инкрементируется метагенератором.
   static const char* name() { return "type1"; }
   static int count() { return 2; }
   static const char** methods() {
      static const char* names[] = { "size" , "message" , 0 };
      return names;
   }

   // accessors
   void size (const std::size_t & v) { boost::fusion::get<0>(*this) = v; }
   const std::size_t& size () const { return boost::fusion::get<0>(*this); }
   void message (const std::string & v) { boost::fusion::get<1>(*this) = v; }
   const std::string& message () const { return boost::fusion::get<1>(*this); }

private:
   friend class boost::serialization::access;
   template<typename archive_type>
   void serialize(archive_type& ar, const unsigned int) {
      ar & boost::fusion::get<0>(*this)
         & boost::fusion::get<1>(*this) ;
   }
};

struct type2: boost::fusion::tuple< std::string, std::string, std::string > {
   type2() {}
   type2(const type2& o)
      :boost::fusion::tuple< std::string, std::string, std::string>(o)
   {}
   type2( const std::string & a0 , const std::string & a1 , const std::string & a2 )
      :boost::fusion::tuple< std::string, std::string, std::string >( a0 , a1 , a2 )
   {}

   // вспомогательные методы
   enum { id = 2 }; // для метакода. инкрементируется метагенератором.
   static const char* name() { return "type2"; }
   static int count() { return 3; }
   static const char** methods() {
      static const char* names[] = { "string" , "code" , "message" , 0 };
      return names;
   }

   // accessors
   void string (const std::string & v) { boost::fusion::get<0>(*this) = v; }
   const std::string& string () const { return boost::fusion::get<0>(*this); }
   void code (const std::string & v) { boost::fusion::get<1>(*this) = v; }
   const std::string& code () const { return boost::fusion::get<1>(*this); }
   void message (const std::string & v) { boost::fusion::get<2>(*this) = v; }
   const std::string& message () const { return boost::fusion::get<2>(*this); }

private:
   friend class boost::serialization::access;
   template<typename archive_type>
   void serialize(archive_type& ar, const unsigned int) {
      ar & boost::fusion::get<0>(*this)
         & boost::fusion::get<1>(*this)
         & boost::fusion::get<2>(*this) ;
   }
};

struct type3: boost::fusion::tuple< int, int, room_t > {
   type3() {}
   type3(const type3& o)
      :boost::fusion::tuple< int, int, room_t>(o)
   {}
   type3( const int & a0 , const int & a1 , const room_t & a2 )
      :boost::fusion::tuple< int, int, room_t >( a0 , a1 , a2 )
   {}

   // вспомогательные методы
   enum { id = 3 }; // для метакода. инкрементируется метагенератором.
   static const char* name() { return "type3"; }
   static int count() { return 3; }
   static const char** methods() {
      static const char* names[] = { "from" , "to" , "inbound" , 0 };
      return names;
   }

   // accessors
   void from (const int & v) { boost::fusion::get<0>(*this) = v; }
   const int& from () const { return boost::fusion::get<0>(*this); }
   void to (const int & v) { boost::fusion::get<1>(*this) = v; }
   const int& to () const { return boost::fusion::get<1>(*this); }
   void inbound (const room_t & v) { boost::fusion::get<2>(*this) = v; }
   const room_t& inbound () const { return boost::fusion::get<2>(*this); }

private:
   friend class boost::serialization::access;
   template<typename archive_type>
   void serialize(archive_type& ar, const unsigned int) {
      ar & boost::fusion::get<0>(*this)
         & boost::fusion::get<1>(*this)
         & boost::fusion::get<2>(*this) ;
   }
};



использовать так:
Код


#include <iostream>
#include <boost/fusion/algorithm/iteration/for_each.hpp>
#include <boost/fusion/include/for_each.hpp>

#include "typedefs.hpp"

template<typename T>
struct printer {
   void operator()(const T& v) const {
      std::cout << v << std::endl;
   }
};

int main() {
   room_t room("room1", {"11", "foo", "anyfoo"});
   type1 t1(32, "any message...");
   type2 t2("string", "code", "message...");
   type3 t3(105, 107, room);

   // сериализуем
   {  boost::archive::text_oarchive(std::cout) << t3;
      std::cout << std::endl;
   }

   // алгоритмы boost.fusion
   boost::fusion::for_each(
      t2,
      printer<std::string>()
   );
   
   return 0;
}


надеюсь оцените мой труд smile 

зы
файлы во вложении.

Автор: bsa 6.5.2011, 20:10
boostcoder, не думал предложить включить это в boost? Может, тебе еще какие интересные идеи по оптимизации предложили бы?

Автор: boostcoder 6.5.2011, 20:52
Цитата(bsa @  6.5.2011,  20:10 Найти цитируемый пост)
не думал предложить включить это в boost?

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

зы
на днях дополню кодогенератор так, чтоб в сгенеренных типах методы name()/count()/methods() были constexpr. это позволит использовать сгенеренные типы совместно с mpl контейнерами.

Автор: mes 6.5.2011, 21:30
Цитата(boostcoder @  6.5.2011,  19:52 Найти цитируемый пост)
 чтоб в сгенеренных типах методы name()/count()/methods() были constexpr

a еще, имхо, неплохо было бы их вынести за пределы пользовательского (генерируемого) класса...
как впрочем и метагенериацию не мешало бы разделить на "слои".. 



Автор: boostcoder 6.5.2011, 21:44
Цитата(mes @  6.5.2011,  21:30 Найти цитируемый пост)
вынести за пределы пользовательского (генерируемого) класса...

не понял...
все равно ведь никто не будет копашиться в сгенерированном коде.. смысл в чем?

Цитата(mes @  6.5.2011,  21:30 Найти цитируемый пост)
разделить на "слои"

тоже не понял..

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

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

Автор: boostcoder 6.5.2011, 22:09
не знаю...стОит ли добавлять constexpr?
id - все равно enum.

т.е. такой код возможен:
Код

template<typename T>
struct item: boost::mpl::pair<boost::mpl::int_<T::_id>, T> {};

typedef boost::mpl::map<
   item<room_t>,
   item<type1>,
   item<type2>,
   item<type3>
> types_map;



добавил генерацию operator<< () в поток.

Автор: bsa 6.5.2011, 22:56
boostcoder, думаю, если ты сможешь добиться исключения явного подключения финишного хидера, то можешь смело отправлять в буст. Даже если тебя пошлют, то дадут ряд советов, как сделать так, чтобы не послали.

Автор: mes 6.5.2011, 23:01
Цитата(boostcoder @  6.5.2011,  20:44 Найти цитируемый пост)
 смысл в чем?

1. будет удобней искать ошибку
2. большая защита коллизий
3. шаг к рантайм-типу
4. шире простор деятельности.. 
5.. 
в общем эта куча на меня производит негативное впечатление, и я много много раз подумал бы, чтоб начать использовать подобное..

Добавлено через 1 минуту и 13 секунд
Цитата(bsa @  6.5.2011,  21:56 Найти цитируемый пост)
то можешь смело отправлять в буст

а в бусте то оно зачем ?!

Автор: mes 6.5.2011, 23:25
Цитата(mes @  6.5.2011,  22:01 Найти цитируемый пост)
5.. 

вынести лишнее в cpp..

вот первый набросок , на основе результативной структуры room_t : http://liveworkspace.org/code/853f1fea8e5264613d6a735a7b46a261

Автор: boostcoder 6.5.2011, 23:33
Цитата(mes @  6.5.2011,  23:25 Найти цитируемый пост)
первый набросок , на основе результативной структуры room_t : http://liveworkspace.org/code/853f1fea8e52...d6a735a7b46a261 

а это идея!

Добавлено через 1 минуту и 31 секунду
вот только это:
Код

// .cpp begin
const char*  type<room_t>::name() { return "room_t"; }

const char** type<room_t>::methods() {
      static const char* names[] = { "name" , "inbound" , 0 };
      return names;
}   
//.cpp end

я понятия не имею как сделать..ведь все генерится в одной файловой единице..

Добавлено через 3 минуты и 41 секунду
можно так: http://liveworkspace.org/code/901c72dce34191e5c1318da49939ef96

Автор: boostcoder 6.5.2011, 23:48
все равно не понимаю для чего аксессоры оставлять внутри, а эти методы выносить..

Автор: mes 6.5.2011, 23:59
Цитата(boostcoder @  6.5.2011,  22:33 Найти цитируемый пост)
ведь все генерится в одной файловой единице..

а зачем все генерить в одной единице ?
почему нельзя генерить отдельно интерфейс, отдельно реализацию ?

Добавлено через 29 секунд
Цитата(boostcoder @  6.5.2011,  22:48 Найти цитируемый пост)
все равно не понимаю для чего аксессоры оставлять внутри, а эти методы выносить.. 

пока сам не знаю..  smile 

Автор: boostcoder 7.5.2011, 00:06
Цитата(mes @  6.5.2011,  23:59 Найти цитируемый пост)
почему нельзя генерить отдельно интерфейс, отдельно реализацию ?

можно.
но в этом случае придется написать два макроса. один вписывать в .hpp файле со всеми параметрами. а второй в .cpp файле, так же, со всеми параметрами.. а если случиться несоответствие между параметрами, то понять причину ошибки будет очень не просто smile

Добавлено @ 00:07
а это, как раз основная причина из-за которой недолюбливают препроцессорную кодогенерацию.

Автор: mes 7.5.2011, 00:20
Цитата(boostcoder @  6.5.2011,  23:06 Найти цитируемый пост)
, со всеми параметрами.

что подразумевается под "всеми параметрами" ?

Добавлено через 1 минуту и 2 секунды
Цитата(boostcoder @  6.5.2011,  22:48 Найти цитируемый пост)
для чего аксессоры оставлять внутри

кстати зачем все так сложно ? 
зачем аксессоры ? зачем наследование ?

Добавлено через 4 минуты и 40 секунд
что должна уметь Ваша структура ?
1. иметь наиболее близкий к классическому интерфейсу структуры
2. уметь отобразить строковые  имена структуры и методов
3. являться/преобразоваться к tuple 
4. сериализоваться и выводиться в поток, но это avtomatizirovano na osnovanii punkta 2.. 

что еще ?

Автор: boostcoder 7.5.2011, 00:35
Цитата(mes @  7.5.2011,  00:20 Найти цитируемый пост)
что подразумевается под "всеми параметрами" ?

это:
Код

   ((room_t,
      ((std::string, name))
      ((std::vector<std::string>, inbound))
   ))
   ((type1,
      ((std::size_t, size))
      ((std::string, message))
   ))
   ((type2,
      ((std::string, string))
      ((std::string, code))
      ((std::string, message))
   ))
   ((type3,
      ((int, from))
      ((int, to))
      ((room_t, inbound))
   ))



Цитата(mes @  7.5.2011,  00:20 Найти цитируемый пост)
что должна уметь Ваша структура ?
1. иметь наиболее близкий к классическому интерфейсу структуры
2. уметь отобразить строковые  имена структуры и методов
3. являться/преобразоваться к tuple 
4. сериализоваться и выводиться в поток


угу. это все.

Добавлено через 42 секунды
ну и иметь еще уникальный id, который можно использовать в компайл-тайм.

Автор: mes 7.5.2011, 00:52
Цитата(boostcoder @  6.5.2011,  23:35 Найти цитируемый пост)
это:

просто придется лишние файлы делать.. 
defs.hpp
inc.hpp
src.hpp
где два последних включают defs между своих метаген инклудов
а все остальные пользуют inc.hpp

Добавлено через 4 минуты и 24 секунды
второй набросок : http://liveworkspace.org/code/bd091abb264fa3147a4979a83bb2d449

Автор: boostcoder 7.5.2011, 01:00
Цитата(mes @  7.5.2011,  00:52 Найти цитируемый пост)
второй набросок : http://liveworkspace.org/code/bd091abb264f...a4979a83bb2d449

хм.. очень даже узабильно smile

Добавлено через 4 минуты и 59 секунд
Цитата(mes @  7.5.2011,  00:52 Найти цитируемый пост)
просто придется лишние файлы делать.. 
defs.hpp
inc.hpp
src.hpp
где два последних включают defs между своих метаген инклудов
а все остальные пользуют inc.hpp

осталось понять для чего это нужно smile 

Автор: mes 7.5.2011, 01:14
Цитата(boostcoder @  7.5.2011,  00:00 Найти цитируемый пост)
осталось понять для чего это нужно   

если нужна возможность разделения на интерфейс и реализацию...

Добавлено через 1 минуту и 17 секунд
Цитата(boostcoder @  7.5.2011,  00:00 Найти цитируемый пост)
хм.. очень даже узабильно

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

Автор: boostcoder 7.5.2011, 01:18
Цитата(mes @  7.5.2011,  01:14 Найти цитируемый пост)
если нужна возможность разделения на интерфейс и реализацию

что разделять, если это генерирует препроцессор? Вы ведь глазами тот код не увидите smile

Добавлено через 1 минуту и 35 секунд
или Вы предлагаете сначала вручную запускать препроцессор чтоб он сгенерил что нужно, а потом использовать сгенеренное как единицу трансляции?

Автор: mes 7.5.2011, 01:22
Цитата(boostcoder @  7.5.2011,  00:18 Найти цитируемый пост)
или Вы предлагаете сначала вручную запускать препроцессор чтоб он сгенерил что нужно, а потом использовать сгенеренное как единицу трансляции? 

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

Добавлено через 1 минуту и 10 секунд
Цитата(boostcoder @  7.5.2011,  00:18 Найти цитируемый пост)
что разделять, если это генерирует препроцессор? Вы ведь глазами тот код не увидите 

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

Добавлено через 1 минуту и 45 секунд
набросок 3: http://liveworkspace.org/code/c127b050f95c2b57f83b624536fc1b6b

Добавлено через 3 минуты и 35 секунд
при втором варианте описания (см. ссылку) теряем возможность автоматического id, в полезности которого я сомневаюсь..зато развязаны руки по оформлению класса...

Автор: boostcoder 7.5.2011, 01:39
Цитата(mes @  7.5.2011,  01:22 Найти цитируемый пост)
в нужной единице трансляции будет включена typedefs как реализация, а в остальных, как интерфейс

это все хорошо.. Вы мне просто скажите: для чего это нужно? ну генерирует он себе код - пусть генерирует...

Цитата(mes @  7.5.2011,  01:22 Найти цитируемый пост)
в одном случае результатом был интерфейс, в другом реализация

может тогда оставить генерацию как есть? ;)

Цитата(mes @  7.5.2011,  01:22 Найти цитируемый пост)
теряем возможность автоматического id, в полезности которого я сомневаюсь

неее. id - как раз нужен...

Автор: mes 7.5.2011, 01:48
Цитата(boostcoder @  7.5.2011,  00:39 Найти цитируемый пост)
это все хорошо.. Вы мне просто скажите: для чего это нужно? ну генерирует он себе код - пусть генерирует...

может и не нужно.. smile

Добавлено @ 01:49
Цитата(boostcoder @  7.5.2011,  00:39 Найти цитируемый пост)

неее. id - как раз нужен...

подумаем , как его добыть..

Добавлено @ 01:50
Цитата(boostcoder @  7.5.2011,  00:39 Найти цитируемый пост)
 id - как раз нужен...

P.S. понимаю что id нужен, я не вижу выгоды в зависимости id от countera..

Добавлено @ 01:59
я бы наверно привел бы к такому виду :
Код

METAGEN_ENUM (ids, room_t, a_t, b_t )


struct room_t
{
     std::string name;
     std::string inbound
     
     METAGEN(meta, room_t, (name, inbound))
};


набросок 4 : http://liveworkspace.org/code/82114ed27eeb4017daa18f3339d378c0

если коллизии не сильно беспокоят, то набросок 5 : http://liveworkspace.org/code/fccd8f937463b427ef3458ef316c7969
вернулись к началу, но с другой стороны     smile 
 

Автор: boostcoder 7.5.2011, 02:23
Цитата(mes @  7.5.2011,  01:48 Найти цитируемый пост)
не вижу выгоды в зависимости id от countera

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

ну есть у меня файлик в ~4000 строк, в котором описаны все типы. да, куча. ну ничего. комментирование очень помогает smile 

Автор: mes 7.5.2011, 08:53
Цитата(boostcoder @  7.5.2011,  01:23 Найти цитируемый пост)
это скорее единственный выход.. 

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


P.S. struct ids можно заменить на namespace ids ..

Автор: boostcoder 7.5.2011, 15:03
Цитата(mes @  7.5.2011,  08:53 Найти цитируемый пост)
а чем не нравится выход предложенный выше в последнем посте ?

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

Автор: mes 7.5.2011, 19:03
Цитата(boostcoder @  7.5.2011,  14:03 Найти цитируемый пост)
а какой смысл писать руками то, что можно не писать? при учете того, что результат одинаковый. 

так результат не совсем одинаковый.. 
в большей степени выбор зависит от того, для чего используется этот ид..
а так да .. "на вкус и цвет товарища нет" smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)