Подскажите хороший синтаксис
От: Went  
Дата: 10.09.11 17:47
Оценка:
Здравствуйте.
Подскажите, как можно наиболее красиво изобразить следующее определение. В коде мы пишем что-то лаконичное вроде:
// some.h, псевдокод
defclass(newtype, sometype, sometext, sometypes);

Эта строка должна определить новый класс newtype, наследованный от sometype, хранящий указатель на строку sometext, и хранящая в себе значению элементы типов sometypes.
Например, код
defclass(NewClass, BaseClass, "This is new class", (int, float));

Должен привестись к такому:
сlass NewClass : public BaseClass
{
public:
  NewClass(int a0, float a1)
  : m_text("This is new class")
  , m_arg0(a0)
  , m_arg1(a1)
  {
  }

private:
  int   m_arg0;
  float m_arg1;
  const char* m_text;
}

Думаю, смысл ясен и задача более чем распространенная.
Какие варианты я рассмотрел:
1. Через шаблон:
// Использование
typdef NewClass MyCoolTemplate<BaseClass, "This is new class", int, float>;

Клевый вариант, но как протащить текст? Чтобы при этом не плодить новые типы в каждой единице компиляции?

2. Через макрос
#define defclass(type, base, text, ...) \
class type : public base \
{ \
public: \
  type(__VA_ARGS__) {} \ // Вот тут палево, как передать __VA_ARGS__ в туплу конструктором?
  boost::tuple<__VA_ARGS__> args;\
}
// Использование
defclass(NewClass, BaseClass, "my cool text", int, float);

Тоже нормальный, но там проблема в конструкторе.

3. 2-ой вариант, но через ацкий BOOST_PREPROCESSOR. Долго читал мануалы, но так и не понял, как мне эти параметры перенести куда надо...

Какие идеи есть у вас?
Re: Подскажите хороший синтаксис
От: uzhas Ниоткуда  
Дата: 10.09.11 20:09
Оценка: +1
Здравствуйте, Went, Вы писали:

W>Думаю, смысл ясен и задача более чем распространенная.

не распространенная и имхо ненужная
возьмите другой язык, если вас не устраивает объявления\определения классов в C++
Re: Подскажите хороший синтаксис
От: rg45 СССР  
Дата: 10.09.11 21:33
Оценка: +1
Здравствуйте, Went, Вы писали:

W>Здравствуйте.

W>Подскажите, как можно наиболее красиво изобразить следующее определение. В коде мы пишем что-то лаконичное вроде:
W>
W>// some.h, псевдокод
W>defclass(newtype, sometype, sometext, sometypes);
W>

W>Эта строка должна определить новый класс newtype, наследованный от sometype, хранящий указатель на строку sometext, и хранящая в себе значению элементы типов sometypes.

А вариант генерации cpp-исходников не рассматриваешь?
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[2]: Подскажите хороший синтаксис
От: Went  
Дата: 11.09.11 03:43
Оценка:
Здравствуйте, uzhas, Вы писали:

U>не распространенная и имхо ненужная

U>возьмите другой язык, если вас не устраивает объявления\определения классов в C++

Хм. Идея. Как-то не догадался, что для того, чтобы лаконично определить семейство схожих классов, проще всего переписать весь проект на другой язык.
Re[2]: Подскажите хороший синтаксис
От: Went  
Дата: 11.09.11 03:44
Оценка:
Здравствуйте, rg45, Вы писали:

R>А вариант генерации cpp-исходников не рассматриваешь?


Неа. Слишком тяжелый вариант для такой тривиальной задачи. К тому же, нужен h-ник
Re: Подскажите хороший синтаксис
От: MasterZiv СССР  
Дата: 11.09.11 07:10
Оценка:
On 10.09.2011 21:47, Went wrote:
> Какие идеи есть у вас?

Вообще конечно надо делать макрос. Хотя в С++ это -- ересь.
А так -- либо переходи на Common Lisp (у тебя мысль работает в этом
направлении), либо лучше
сделай не 200 классов, а один универсальный с массивом вариантов.
Posted via RSDN NNTP Server 2.1 beta
Re: Подскажите хороший синтаксис
От: jazzer Россия Skype: enerjazzer
Дата: 11.09.11 08:05
Оценка:
Здравствуйте, Went, Вы писали:

W>3. 2-ой вариант, но через ацкий BOOST_PREPROCESSOR. Долго читал мануалы, но так и не понял, как мне эти параметры перенести куда надо...


Все там просто, только надо список типов задавать не через запятую — это PP_TUPLE, которого ты должен знать размер, а через безразмерное, например, PP_SEQ: (int)(double)(...)

W>Какие идеи есть у вас?


Раз тебе пофиг на имена полей — используй просто boost::tuple или (лучше) boost::fusion::vector.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re: Подскажите хороший синтаксис
От: locker  
Дата: 11.09.11 14:28
Оценка:
а в чем смысл?
если неизвестно как будут называться члены класса
то как его использовать?
или там будут всегда разные типы?
но все равно как к ним обращаться?
Re[2]: Подскажите хороший синтаксис
От: Доктор ТуамОсес Гондурас Мой новый проект "ВЕПРЬ-1"
Дата: 11.09.11 15:24
Оценка: :)
Здравствуйте, locker, Вы писали:

L>а в чем смысл?

L>если неизвестно как будут называться члены класса
L>то как его использовать?
Почему неизвестно?
Так и будут: arg_1? arg_2 и т.д.
Мой новый проект "ВЕПРЬ-1"
Re[3]: Подскажите хороший синтаксис
От: locker  
Дата: 11.09.11 16:04
Оценка: +1
Здравствуйте, Доктор ТуамОсес, Вы писали:

ДТ>Здравствуйте, locker, Вы писали:


L>>а в чем смысл?

L>>если неизвестно как будут называться члены класса
L>>то как его использовать?
ДТ>Почему неизвестно?
ДТ>Так и будут: arg_1? arg_2 и т.д.
это что получается, надо помнить какой порядок
членов класса и писать arg_1...
это разве нормально?
Re[4]: Подскажите хороший синтаксис
От: Доктор ТуамОсес Гондурас Мой новый проект "ВЕПРЬ-1"
Дата: 11.09.11 16:24
Оценка:
Здравствуйте, locker, Вы писали:

L>Здравствуйте, Доктор ТуамОсес, Вы писали:


ДТ>>Здравствуйте, locker, Вы писали:


L>>>а в чем смысл?

L>>>если неизвестно как будут называться члены класса
L>>>то как его использовать?
ДТ>>Почему неизвестно?
ДТ>>Так и будут: arg_1? arg_2 и т.д.
L>это что получается, надо помнить какой порядок
L>членов класса и писать arg_1...
L>это разве нормально?

Ну Вас же не смущает, что нужно запоминать порядок следования фактических параметров (т.е. какой за что отвечает) при вызове метода?
Мой новый проект "ВЕПРЬ-1"
Re[2]: Подскажите хороший синтаксис
От: Went  
Дата: 12.09.11 07:44
Оценка:
Здравствуйте, MasterZiv, Вы писали:

MZ>Вообще конечно надо делать макрос. Хотя в С++ это -- ересь.


Ну, объявить уникальный тип без макроса не выйдет. Тайпдефом можно, но только если вводить некий уникальный ИД класса как один из аргументов шаблона.

MZ>А так -- либо переходи на Common Lisp (у тебя мысль работает в этом

MZ>направлении)



MZ>сделай не 200 классов, а один универсальный с массивом вариантов.


Так типы-то разные. Где-то может быть int+float, а где-то shared_ptr<std::string>.
Re[2]: Подскажите хороший синтаксис
От: Went  
Дата: 12.09.11 07:50
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Все там просто, только надо список типов задавать не через запятую — это PP_TUPLE, которого ты должен знать размер, а через безразмерное, например, PP_SEQ: (int)(double)(...)


Да, я пытался, но возникли 2 проблемы:
1. Как объявить "пустую" SEQ? Если ничего не писать, при развороте оказываются куча ворнингов и винегрет в конце.
2. Как потом преобразовать имеющуюся SEQ вида (int)(float) к:
а) int p1, float p2 — нужно для описания параметров конструктора класса;
б) p1, p2 — нужно как фактические параметры для вызова конструктора туплы.
Вроде доки есть, но как начинаешь что-то городить, оказывается, что есть все, кроме того, что тебе нужно.

J>Раз тебе пофиг на имена полей — используй просто boost::tuple или (лучше) boost::fusion::vector.

Да я-то и использую, но проблема с конструированием, описанная выше, печалит.
Re[2]: Подскажите хороший синтаксис
От: Went  
Дата: 12.09.11 07:53
Оценка:
Здравствуйте, locker, Вы писали:

L>а в чем смысл?

L>если неизвестно как будут называться члены класса
L>то как его использовать?
L>или там будут всегда разные типы?
L>но все равно как к ним обращаться?

Они называются arg1 ... argN. Большинство работы с ними будет внутри класса, и их предназначение будет написано в камменте, если потребуется обратиться снаружи. Это почти как тупла — там же члены имеют просто номера, но это не мешает их использовать без проблем.
Re[3]: Подскажите хороший синтаксис
От: MasterZiv СССР  
Дата: 12.09.11 07:54
Оценка:
On 12.09.2011 11:44, Went wrote:

> MZ>сделай не 200 классов, а один универсальный с массивом вариантов.

>
> Так типы-то разные. Где-то может быть int+float, а где-то shared_ptr<std::string>.

Массив вариантных структур.
Posted via RSDN NNTP Server 2.1 beta
Re[3]: Подскажите хороший синтаксис
От: jazzer Россия Skype: enerjazzer
Дата: 12.09.11 09:24
Оценка: 3 (1)
Здравствуйте, Went, Вы писали:

W>Здравствуйте, jazzer, Вы писали:


J>>Все там просто, только надо список типов задавать не через запятую — это PP_TUPLE, которого ты должен знать размер, а через безразмерное, например, PP_SEQ: (int)(double)(...)


W>Да, я пытался, но возникли 2 проблемы:


Сначала вторую:
W>2. Как потом преобразовать имеющуюся SEQ вида (int)(float) к:
W> а) int p1, float p2 — нужно для описания параметров конструктора класса;
W> б) p1, p2 — нужно как фактические параметры для вызова конструктора туплы.
W>Вроде доки есть, но как начинаешь что-то городить, оказывается, что есть все, кроме того, что тебе нужно.
Значит, смотришь не туда, а смотреть надо сюда: http://www.boost.org/libs/preprocessor/doc/ref/seq_for_each_i.html
Просто по примерам оттуда получаешь вот такое:
#define CTOR(r, data, i, elem) , BOOST_PP_CAT(m_arg, i)(BOOST_PP_CAT(a, i))CRLF 
#define MEMB(r, data, i, elem) elem BOOST_PP_CAT(m_arg, i);CRLF 
#define ARGS(r, data, i, elem) BOOST_PP_COMMA_IF(i) elem BOOST_PP_CAT(a, i)

#define defclass_seq(C,B,S,seq)           \
class C : public B                        \
{                                         \
public:                                   \
  C(BOOST_PP_SEQ_FOR_EACH_I(ARGS,_, seq)) \
  : m_text(S)                             \
  BOOST_PP_SEQ_FOR_EACH_I(CTOR,_, seq)    \
  {                                       \
  }                                       \
                                          \
private:                                  \
  BOOST_PP_SEQ_FOR_EACH_I(MEMB,_, seq)    \
  const char* m_text;                     \
}



W>1. Как объявить "пустую" SEQ? Если ничего не писать, при развороте оказываются куча ворнингов и винегрет в конце.

BOOST_PP_SEQ_NIL: http://www.boost.org/libs/preprocessor/doc/ref/seq_nil.html
Сначала надо объявить макро для пустой последовательности:
#define defclass_empty(C,B,S,seq)         \
class C : public B                        \
{                                         \
public:                                   \
  C()                                     \
  : m_text(S)                             \
  {                                       \
  }                                       \
                                          \
private:                                  \
  const char* m_text;                     \
}


А потом устроить выбор между ними двумя вот примерно так:
#define defclass(C,B,S,seq)                                           \
  BOOST_PP_IIF(                                                       \
    BOOST_PP_EQUAL(BOOST_PP_SEQ_SIZE(BOOST_PP_SEQ_PUSH_BACK(seq,x)),1)\
    , defclass_empty                                                  \
    , defclass_seq )(C,B,S,seq)


BOOST_PP_SEQ_PUSH_BACK нужен из-за особенностей работы BOOST_PP_SEQ_NIL

J>>Раз тебе пофиг на имена полей — используй просто boost::tuple или (лучше) boost::fusion::vector.

W>Да я-то и использую, но проблема с конструированием, описанная выше, печалит.
Это ты строчку имеешь в виду? Потому что остальные проблемы влёгкую решаются вариадик-шаблоном.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[4]: Подскажите хороший синтаксис
От: Went  
Дата: 12.09.11 14:08
Оценка:
Здравствуйте, jazzer.
Огромное спасибо! Блин, мне потребуются сутки чтобы разобраться в этом решении
Re[5]: Подскажите хороший синтаксис
От: jazzer Россия Skype: enerjazzer
Дата: 12.09.11 18:19
Оценка:
Здравствуйте, Went, Вы писали:

W>Здравствуйте, jazzer.

W>Огромное спасибо! Блин, мне потребуются сутки чтобы разобраться в этом решении

Всегда рад помочь. Спрашивай, если что непонятно.
Да, убери там CRLF — это вспомогательная фигня для разбивки строк макроса, а то я в паре мест забыл почистить
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.