boost.preprocessor не разворачивает макровызовы, почему-то
снова здравствуйте!
есть такой код:
#include <boost/preprocessor.hpp>
/***************************************************************************/
#define CONSTRUCT_CONCRETE_proc(name, tuple) /* макровызов обработки последовательности для proc-типов */ \
myproc[name: BOOST_PP_TUPLE_ENUM tuple]
#define CONSTRUCT_CONCRETE_enum(name, tuple) /* макровызов обработки последовательности для enum-типов */ \
myenum[name: BOOST_PP_TUPLE_ENUM tuple]
#define CONSTRUCT_PROCS(unused, idx, seq) /* тут конкатинируем 'CONSTRUCT_CONCRETE_' и 'proc' или 'enum', и экспандим его */ \
BOOST_PP_EXPAND(BOOST_PP_CAT(CONSTRUCT_CONCRETE_, BOOST_PP_SEQ_ELEM(idx, seq)))
#define CONSTRUCT(name, seq) \
struct name { \
BOOST_PP_REPEAT( \
BOOST_PP_SEQ_SIZE(seq) \
,CONSTRUCT_PROCS \
,seq \
) \
}; /* struct name */
/***************************************************************************/
CONSTRUCT(
type1
,
(proc(m0, (float )))
(proc(m1, (int , long )))
(enum (mye1, (e0, e1, e2)))
)
/***************************************************************************/
суть кода — получить возможность обрабатывать последовательности типов разными способами.
сейчас, при препроцессировании, получаю такой код:
struct type1 {
myproc[m0: BOOST_PP_CAT(BOOST_PP_TUPLE_REM_CTOR_O_, 1)(float )]
myproc[m1: BOOST_PP_CAT(BOOST_PP_TUPLE_REM_CTOR_O_, 2)(int , long )]
myenum[mye1: BOOST_PP_CAT(BOOST_PP_TUPLE_REM_CTOR_O_, 3)(e0, e1, e2)]
};
этот код полностью валиден, за исключением того, что эти строки начинающиеся с 'BOOST_PP_CAT' — должны обрабатываться препроцессором, чего не происходит.
не понимаю, от чего так?
спасибо.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re: boost.preprocessor не разворачивает макровызовы, почему-то
От:
Vain
google.ru
Дата: 12.01.14 20:16
Оценка:
Здравствуйте, niXman, Вы писали:
X>#define CONSTRUCT_PROCS(unused, idx, seq) /* тут конкатинируем 'CONSTRUCT_CONCRETE_' и 'proc' или 'enum', и экспандим его */ \
X> BOOST_PP_EXPAND(BOOST_PP_CAT(CONSTRUCT_CONCRETE_, BOOST_PP_SEQ_ELEM(idx, seq)))
Может так поможет?
BOOST_PP_EXPAND(BOOST_PP_CAT)(CONSTRUCT_CONCRETE_, BOOST_PP_SEQ_ELEM(idx, seq))
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re[2]: boost.preprocessor не разворачивает макровызовы, почему-то
Здравствуйте, Vain, Вы писали:
V>Может так поможет?
V>V>BOOST_PP_EXPAND(BOOST_PP_CAT)(CONSTRUCT_CONCRETE_, BOOST_PP_SEQ_ELEM(idx, seq))
V>
нет, не помогло. абсолютно без изменений.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[3]: boost.preprocessor не разворачивает макровызовы, почему-то
От:
Vain
google.ru
Дата: 12.01.14 23:28
Оценка:
Здравствуйте, niXman, Вы писали:
X>нет, не помогло. абсолютно без изменений.
Можно ещё проверить правда ли то, что выдал препроцессор пытается компилировать компилятор. Для этого можно результат препроцессора скормить опять компилятору и сравнить номера ошибок. Они должны совпадать.
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re[4]: boost.preprocessor не разворачивает макровызовы, почему-то
так код же не полностью препроцессирован. какой смысл его компилировать?
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re: boost.preprocessor не разворачивает макровызовы, почему-то
Здравствуйте, niXman, Вы писали:
А если так:
/***************************************************************************/
#define CONSTRUCT_CONCRETE_proc(name, tuple) /* макровызов обработки последовательности для proc-типов */ \
(name)(tuple)
#define CONSTRUCT_CONCRETE_enum(name, tuple) /* макровызов обработки последовательности для enum-типов */ \
(name)(tuple)
#define GET_MACRO(sub_macro) myproc[BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(0,BOOST_PP_CAT(CONSTRUCT_CONCRETE_, sub_macro)),:) BOOST_PP_TUPLE_ENUM(BOOST_PP_SEQ_ELEM(1,BOOST_PP_CAT(CONSTRUCT_CONCRETE_, sub_macro)))]
#define CONSTRUCT_PROCS(unused, idx, seq) /* тут конкатинируем 'CONSTRUCT_CONCRETE_' и 'proc' или 'enum', и экспандим его */ \
GET_MACRO(BOOST_PP_SEQ_ELEM(idx, seq))
#define CONSTRUCT(name, seq) \
struct name { \
BOOST_PP_REPEAT( \
BOOST_PP_SEQ_SIZE(seq) \
,CONSTRUCT_PROCS \
,seq \
) \
}; /* struct name */
/***************************************************************************/
CONSTRUCT(
type1
,
(proc(m0, (float )))
(proc(m1, (int , long )))
(enum (mye1, (e0, e1, e2)))
)
Aутпут:
struct type1 { myproc[m0: float] myproc[m1: int, long] myproc[mye1: e0, e1, e2] };
Думаю иде должна быть ясна. По сути, раскрываем полученный сиквенс в конкретных макросах, макросом из вне.
Если нужно, можно "специализировать" какие то еще дополнительные аргументы в сиквенсе в самих CONSTRUCT_CONCRETE_proc/CONSTRUCT_CONCRETE_enum а раскрыть их в GET_MACRO
p.s.
Вся "сложность" этих макросов, то что в голове постоянно нужен держать одно очень важное правило — препроцессор штука однопроходная.
Со временем можно легко натаскаться и писать их будет значительно проще, особенно с такой мощной либой как boost::preprocessor
Re[2]: boost.preprocessor не разворачивает макровызовы, почему-то
поправочка
#define CONSTRUCT_CONCRETE_proc(name, tuple) /* макровызов обработки последовательности для proc-типов */ \
(name)(tuple)(myproc)
#define CONSTRUCT_CONCRETE_enum(name, tuple) /* макровызов обработки последовательности для enum-типов */ \
(name)(tuple)(myenum)
#define GET_MACRO(sub_macro) BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(2,BOOST_PP_CAT(CONSTRUCT_CONCRETE_, sub_macro)), \
[BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(0,BOOST_PP_CAT(CONSTRUCT_CONCRETE_, sub_macro)),:) BOOST_PP_TUPLE_ENUM(BOOST_PP_SEQ_ELEM(1,BOOST_PP_CAT(CONSTRUCT_CONCRETE_, sub_macro)))] \
)
Re[3]: boost.preprocessor не разворачивает макровызовы, почему-то
спасибо за ответ!
но я, признаться, не понимаю, почему ты сделал то, что сделал. объясни плиз как-то более развернуто, плиз
зы
а твой вариант у тебя препроцессируется нормально, без ошибок?
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[2]: boost.preprocessor не разворачивает макровызовы, почему-то
Здравствуйте, nen777w, Вы писали:
N>важное правило — препроцессор штука однопроходная.
слышал это не единожды, но не уверен, что правильно понимаю. объясни и это, плиз
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[3]: boost.preprocessor не разворачивает макровызовы, почему-то
решил следующим образом:
1. формируем имя нужного макроса
2. извлекаем тьюпл с типами
3. производим макровызов подставляя тьюпл
вопрос закрыт.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[4]: boost.preprocessor не разворачивает макровызовы, почему-то
решить проблему — решил. переключился на другую задачу, а сейчас не могу найти где решение записал. с утра тыркаюсь, а заново решить не получается %)
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[5]: boost.preprocessor не разворачивает макровызовы, почему-то
фух, получилось %)
оставлю-ка я решение тут:
#include <boost/preprocessor.hpp>
/***************************************************************************/
#define YARMI_CONSTRUCT_INVOKER_OPEN_NS_ITEM(unused, data, elem) \
namespace elem {
#define YARMI_CONSTRUCT_INVOKER_OPEN_NS(seq) \
BOOST_PP_SEQ_FOR_EACH( \
YARMI_CONSTRUCT_INVOKER_OPEN_NS_ITEM \
,~ \
,seq \
)
#define YARMI_CONSTRUCT_INVOKER_CLOSE_NS_ITEM(unused1, unused2, data) \
data
#define YARMI_CONSTRUCT_INVOKER_CLOSE_NS(seq) \
BOOST_PP_REPEAT( \
BOOST_PP_SEQ_SIZE(seq) \
,YARMI_CONSTRUCT_INVOKER_CLOSE_NS_ITEM \
,} \
)
/***************************************************************************/
#define NAME_proc(...) \
GEN_proc
#define NAME_code(...) \
GEN_code
#define GEN_proc(name, tuple) \
void name(BOOST_PP_TUPLE_ENUM(tuple)) {}
#define GEN_code(...) \
__VA_ARGS__
#define GET_PROC_NAME(str) \
BOOST_PP_CAT(NAME_, str)
#define ARGS_proc(...) \
__VA_ARGS__
#define ARGS_code(...) \
__VA_ARGS__
#define GET_PROC_ARGS_NAME(str) \
BOOST_PP_CAT(ARGS_, str)
#define EXP(idx, name, args) \
name(args)
#define YARMI_CONSTRUCT_INVOKER_IMPL_AUX(idx, item) \
EXP(idx, GET_PROC_NAME(item), GET_PROC_ARGS_NAME(item))
#define YARMI_CONSTRUCT_INVOKER_IMPL(unused, idx, seq) \
YARMI_CONSTRUCT_INVOKER_IMPL_AUX(idx, BOOST_PP_SEQ_ELEM(idx, seq))
/***************************************************************************/
#define YARMI_CONSTRUCT_INVOKER(reqns, name, seq, oposeq) \
YARMI_CONSTRUCT_INVOKER_OPEN_NS(reqns) \
\
struct name { \
BOOST_PP_REPEAT( \
BOOST_PP_SEQ_SIZE(seq) \
,YARMI_CONSTRUCT_INVOKER_IMPL \
,seq \
) \
}; \
YARMI_CONSTRUCT_INVOKER_CLOSE_NS(reqns)
/***************************************************************************/
#define YARMI_CONSTRUCT( \
reqns \
,reqname \
,reqseq \
,repns \
,repname \
,repseq) \
\
YARMI_CONSTRUCT_INVOKER( \
reqns \
,reqname \
,reqseq \
,repseq \
)
/***************************************************************************/
YARMI_CONSTRUCT(
(ns1)(ns2)(ns3)(ns4),
login_request
,
(code(
private : int v;
public : login_request(int v)
:v(v)
{}
void set_v(int r) { v = r; }
const int get_v() const { return v; }
))
(proc(login, (char , int , double )))
(code(using int_pair = std::pair<int , int >;))
(proc(login, (char , int , double , int_pair)))
(proc(login2, (int , double )))
,
(ns4)(ns3)(ns2)(ns1),
login_reply
,
(code(void f0(){} int f1(){} std::pair<int , int > f2(){}))
(proc(login, (char , int , double )))
)
/***************************************************************************/
результат:
namespace ns1 {
namespace ns2 {
namespace ns3 {
namespace ns4 {
struct login_request {
private :
int v;
public :
login_request(int v)
:v(v)
{}
void set_v(int r) { v = r; }
const int get_v() const { return v; }
void login(char , int , double ) {}
using int_pair = std::pair<int , int >;
void login(char , int , double , int_pair) {}
void login2(int , double ) {}
}; // struct login_request
} // ns4
} // ns3
} // ns2
} // ns1
всем спасибо!
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Пока на собственное сообщение не было ответов, его можно удалить.
Удалить