Эта строка должна определить новый класс 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. Долго читал мануалы, но так и не понял, как мне эти параметры перенести куда надо...
Здравствуйте, Went, Вы писали:
W>Думаю, смысл ясен и задача более чем распространенная.
не распространенная и имхо ненужная
возьмите другой язык, если вас не устраивает объявления\определения классов в C++
Здравствуйте, Went, Вы писали:
W>Здравствуйте. W>Подскажите, как можно наиболее красиво изобразить следующее определение. В коде мы пишем что-то лаконичное вроде: W>
W>Эта строка должна определить новый класс newtype, наследованный от sometype, хранящий указатель на строку sometext, и хранящая в себе значению элементы типов sometypes.
А вариант генерации cpp-исходников не рассматриваешь?
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, uzhas, Вы писали:
U>не распространенная и имхо ненужная U>возьмите другой язык, если вас не устраивает объявления\определения классов в C++
Хм. Идея. Как-то не догадался, что для того, чтобы лаконично определить семейство схожих классов, проще всего переписать весь проект на другой язык.
On 10.09.2011 21:47, Went wrote: > Какие идеи есть у вас?
Вообще конечно надо делать макрос. Хотя в С++ это -- ересь.
А так -- либо переходи на Common Lisp (у тебя мысль работает в этом
направлении), либо лучше
сделай не 200 классов, а один универсальный с массивом вариантов.
Здравствуйте, Went, Вы писали:
W>3. 2-ой вариант, но через ацкий BOOST_PREPROCESSOR. Долго читал мануалы, но так и не понял, как мне эти параметры перенести куда надо...
Все там просто, только надо список типов задавать не через запятую — это PP_TUPLE, которого ты должен знать размер, а через безразмерное, например, PP_SEQ: (int)(double)(...)
W>Какие идеи есть у вас?
Раз тебе пофиг на имена полей — используй просто boost::tuple или (лучше) boost::fusion::vector.
а в чем смысл?
если неизвестно как будут называться члены класса
то как его использовать?
или там будут всегда разные типы?
но все равно как к ним обращаться?
Здравствуйте, locker, Вы писали:
L>а в чем смысл? L>если неизвестно как будут называться члены класса L>то как его использовать?
Почему неизвестно?
Так и будут: arg_1? arg_2 и т.д.
Здравствуйте, Доктор ТуамОсес, Вы писали:
ДТ>Здравствуйте, locker, Вы писали:
L>>а в чем смысл? L>>если неизвестно как будут называться члены класса L>>то как его использовать? ДТ>Почему неизвестно? ДТ>Так и будут: arg_1? arg_2 и т.д.
это что получается, надо помнить какой порядок
членов класса и писать arg_1...
это разве нормально?
Здравствуйте, locker, Вы писали:
L>Здравствуйте, Доктор ТуамОсес, Вы писали:
ДТ>>Здравствуйте, locker, Вы писали:
L>>>а в чем смысл? L>>>если неизвестно как будут называться члены класса L>>>то как его использовать? ДТ>>Почему неизвестно? ДТ>>Так и будут: arg_1? arg_2 и т.д. L>это что получается, надо помнить какой порядок L>членов класса и писать arg_1... L>это разве нормально?
Ну Вас же не смущает, что нужно запоминать порядок следования фактических параметров (т.е. какой за что отвечает) при вызове метода?
Здравствуйте, MasterZiv, Вы писали:
MZ>Вообще конечно надо делать макрос. Хотя в С++ это -- ересь.
Ну, объявить уникальный тип без макроса не выйдет. Тайпдефом можно, но только если вводить некий уникальный ИД класса как один из аргументов шаблона.
MZ>А так -- либо переходи на Common Lisp (у тебя мысль работает в этом MZ>направлении)
MZ>сделай не 200 классов, а один универсальный с массивом вариантов.
Так типы-то разные. Где-то может быть int+float, а где-то shared_ptr<std::string>.
Здравствуйте, 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.
Да я-то и использую, но проблема с конструированием, описанная выше, печалит.
Здравствуйте, locker, Вы писали:
L>а в чем смысл? L>если неизвестно как будут называться члены класса L>то как его использовать? L>или там будут всегда разные типы? L>но все равно как к ним обращаться?
Они называются arg1 ... argN. Большинство работы с ними будет внутри класса, и их предназначение будет написано в камменте, если потребуется обратиться снаружи. Это почти как тупла — там же члены имеют просто номера, но это не мешает их использовать без проблем.
On 12.09.2011 11:44, Went wrote:
> MZ>сделай не 200 классов, а один универсальный с массивом вариантов. > > Так типы-то разные. Где-то может быть int+float, а где-то shared_ptr<std::string>.
Здравствуйте, 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; \
}
А потом устроить выбор между ними двумя вот примерно так:
BOOST_PP_SEQ_PUSH_BACK нужен из-за особенностей работы BOOST_PP_SEQ_NIL
J>>Раз тебе пофиг на имена полей — используй просто boost::tuple или (лучше) boost::fusion::vector. W>Да я-то и использую, но проблема с конструированием, описанная выше, печалит.
Это ты строчку имеешь в виду? Потому что остальные проблемы влёгкую решаются вариадик-шаблоном.
Здравствуйте, Went, Вы писали:
W>Здравствуйте, jazzer. W>Огромное спасибо! Блин, мне потребуются сутки чтобы разобраться в этом решении
Всегда рад помочь. Спрашивай, если что непонятно.
Да, убери там CRLF — это вспомогательная фигня для разбивки строк макроса, а то я в паре мест забыл почистить