2016-02-14 51 views
1

我以編程方式生成C++代碼。我經常有以下形式的輸出鏈表,構建鏈接列表的宏

PTR(new List(a,PTR(new List(NULL,NULL)))) 
PTR(new List(a, PTR(new List(b,PTR(new List(NULL,NULL)))))) 

由於列表的大小可能會生成的代碼變得醜陋我想知道是否有可能定義表單的可變參數宏,

LIST(a) 
LIST(a,b) 

這將擴展到第一種形式的代碼。

+0

是的,Boost.Preprocessor是一個很好的開始。 – chris

+0

@chris,你能指點我一篇文章,說明我該怎麼做?對於嵌入式平臺,我寧願不依賴於單個宏的增強。 –

+0

你當然可以使用Boost.PP而無需Boost的其餘部分。這些都是宏,所以除了你生成的代碼之外,沒有任何代碼。 – chris

回答

1

這裏的one way使用Boost.Preprocessor,它不依賴於加速的任何其他部分:

#include <boost/preprocessor.hpp> 

#define FOR_EACH_OP(r, data, elem) PTR(new List(elem, 
#define DOUBLE_RPAREN(...))) 

#define LIST(...) LIST_I(BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)) 
#define LIST_I(seq) \ 
    BOOST_PP_SEQ_FOR_EACH(FOR_EACH_OP, /*empty*/, seq) \ 
    PTR(new List(NULL,NULL)) \ 
    BOOST_PP_REPEAT(BOOST_PP_SEQ_SIZE(seq), DOUBLE_RPAREN, /*empty*/) 

LIST(a) // PTR(new List(a, PTR(new List(NULL,NULL)))) 
LIST(a,b) // PTR(new List(a, PTR(new List(b, PTR(new List(NULL,NULL)))))) 

LIST只是將爭論變成了「PP序列」,它提供了一個方便的FOR_EACH。對於每個參數,左邊的部分都是建立起來的。然後添加NULL部件。最後,根據給定的參數數量添加匹配的右括號。

聲明:LIST()將無法​​按預期工作,因爲這是一個帶有一個(空)參數的調用。


如果你真的對Boost過敏,你可以make simplified versions of these。例如,支持最多四個參數的一種方法:

#define CAT(_0, _1) CAT_I(_0, _1) 
#define CAT_I(_0, _1) _0##_1 

#define ARG5(_0, _1, _2, _3, _4, ...) _4 
#define NARGS(...) ARG5(__VA_ARGS__, 4, 3, 2, 1,) 
#define OVERLOAD(prefix, ...) CAT(prefix, NARGS(__VA_ARGS__)) 

#define ELEM(i, ...) CAT(ELEM_, i)(__VA_ARGS__,) 
#define ELEM_0(_0, ...) _0 
#define ELEM_1(_0, _1, ...) _1 
#define ELEM_2(_0, _1, _2, ...) _2 
#define ELEM_3(_0, _1, _2, _3, ...) _3 

#define FOR_EACH(macro, ...) OVERLOAD(FOR_EACH_, __VA_ARGS__)(macro, __VA_ARGS__) 
#define FOR_EACH_1(macro, ...) macro(ELEM(0, __VA_ARGS__)) 
#define FOR_EACH_2(macro, ...) FOR_EACH_1(macro, __VA_ARGS__) macro(ELEM(1, __VA_ARGS__)) 
#define FOR_EACH_3(macro, ...) FOR_EACH_2(macro, __VA_ARGS__) macro(ELEM(2, __VA_ARGS__)) 
#define FOR_EACH_4(macro, ...) FOR_EACH_3(macro, __VA_ARGS__) macro(ELEM(3, __VA_ARGS__)) 

#define REPEAT(n, macro) CAT(REPEAT_, n)(macro) 
#define REPEAT_1(macro) macro() 
#define REPEAT_2(macro) REPEAT_1(macro) macro() 
#define REPEAT_3(macro) REPEAT_2(macro) macro() 
#define REPEAT_4(macro) REPEAT_3(macro) macro() 

#define FOR_EACH_MACRO(elem) PTR(new List(elem, 
#define DOUBLE_RPAREN())) 

#define LIST(...) LIST_I(NARGS(__VA_ARGS__), __VA_ARGS__) 
#define LIST_I(n, ...) \ 
    FOR_EACH(FOR_EACH_MACRO, __VA_ARGS__) \ 
    PTR(new List(NULL,NULL)) \ 
    REPEAT(n, DOUBLE_RPAREN) 

LIST(a) // PTR(new List(a, PTR(new List(NULL,NULL)))) 
LIST(a,b) // PTR(new List(a, PTR(new List(b, PTR(new List(NULL,NULL))))))