2012-07-30 60 views
2

我想創建一個定義來分析函數簽名,並使用升壓預處理創造這樣的事情:如何通過預處理器定義獲得函數簽名?

MY_DEFINE std::string fun(int t, float b) 
{ 

或至少:

MY_DEFINE(std::string)(fun)(int t, float b) 
{ 

這將產生:

class fun_in 
{ 
    int t; 
    float b; 
} 

class fun_out 
{ 
    std::string value; 
} 

void my_fun_wrapper(int t, float b) 
{ 
} 

std::string fun(int t, float b) 
{ 
    my_fun_wrapper(t, b); 

用於定義每個函數。

是否有可能創建這樣的定義包裝函數N傳入參數和任何返回類型通過Boost預處理器?

+0

'return'是C++的保留字 - 唐將它用作結構成員名稱。 – 2012-07-30 20:48:58

+0

你想讓'MY_DEFINE'擴展到依賴於它之後的東西嗎? – GManNickG 2012-08-01 20:40:40

+0

'MY_DEFINE type name(type x,type y)'是必需的語法嗎?爲什麼不'MY_DEFINE(type,name,type1,x,type2,y)'或可能有最後一部分可變參數。 – pmr 2012-08-01 20:42:53

回答

4

那麼,預處理器不能在沒有預先告訴它的情況下解析令牌。所以你需要使用更多的括號。下面是它會是什麼樣子:

DEFINE((std::string)(fun)((int) a, (float) b)) 
{ 
    return "Hello World!"; 
} 

下面介紹如何創建使用宏升壓(我假設你熟悉它的預處理器庫)。首先是定義一些宏處理括號,因爲升壓根本不會用逗號處理序列:

#define REM(...) __VA_ARGS__ 
#define EAT(...) 

// Retrieve the type 
#define TYPEOF(x) DETAIL_TYPEOF(DETAIL_TYPEOF_PROBE x,) 
#define DETAIL_TYPEOF(...) DETAIL_TYPEOF_HEAD(__VA_ARGS__) 
#define DETAIL_TYPEOF_HEAD(x, ...) REM x 
#define DETAIL_TYPEOF_PROBE(...) (__VA_ARGS__), 
// Strip off the type 
#define STRIP(x) EAT x 
// Show the type without parenthesis 
#define PAIR(x) REM x 

接下來,你需要處理ARGS以三種不同的方式。首先,將它們輸出爲成員變量(如int a; float b;)。然後作爲函數參數(如(int a, float b))。然後最後作爲前向參數傳遞給另一個函數(如(a, b))。

#define DETAIL_DEFINE_MEMBERS_EACH(r, data, x) PAIR(x); 
#define DETAIL_DEFINE_ARGS_EACH(r, data, i, x) BOOST_PP_COMMA_IF(i) PAIR(x) 
#define DETAIL_DEFINE_FORWARD_EACH(r, data, i, x) BOOST_PP_COMMA_IF(i) STRIP(x) 

#define DETAIL_DEFINE_MEMBERS(args) BOOST_PP_SEQ_FOR_EACH(DETAIL_DEFINE_MEMBERS_EACH, data, BOOST_PP_VARIADIC_TO_SEQ args) 
#define DETAIL_DEFINE_ARGS(args) BOOST_PP_SEQ_FOR_EACH_I(DETAIL_DEFINE_ARGS_EACH, data, BOOST_PP_VARIADIC_TO_SEQ args) 
#define DETAIL_DEFINE_FORWARD(args) BOOST_PP_SEQ_FOR_EACH_I(DETAIL_DEFINE_FORWARD_EACH, data, BOOST_PP_VARIADIC_TO_SEQ args) 

接下來我們創建一個帶有三個參數的DETAIL_DEFINE宏。第一個是函數的名稱,參數,然後是返回值。這將產生類和函數,像你想:

#define DETAIL_DEFINE(name, args, ...) \ 
struct BOOST_PP_CAT(name, _in) \ 
{ \ 
    DETAIL_DEFINE_MEMBERS(args) \ 
}; \ 
struct BOOST_PP_CAT(name, _out) \ 
{ \ 
    __VA_ARGS__ value; \ 
}; \ 
__VA_ARGS__ BOOST_PP_CAT(name, _impl) DETAIL_DEFINE_ARGS(args) ; \ 
__VA_ARGS__ name DETAIL_DEFINE_ARGS(args) \ 
{ \ 
    return BOOST_PP_CAT(name, _impl) DETAIL_DEFINE_FORWARD(args); \ 
} \ 
__VA_ARGS__ BOOST_PP_CAT(name, _impl) DETAIL_DEFINE_ARGS(args) 

最後,DEFINE宏將解析出所有的括號,並將其傳遞給DETAIL_DEFINE宏:所以,當你寫現在

#define DEFINE(x) DETAIL_DEFINE(TYPEOF(STRIP(x)), (TYPEOF(STRIP(STRIP(x)))), TYPEOF(x)) 

DEFINE((std::string)(fun)((int) a, (float) b)) 
{ 
    return "Hello World!"; 
} 

它應該輸出:

struct fun_in 
{ 
    int a; 
    float b; 
}; 
struct fun_out 
{ 
    std::string value; 
}; 
std::string fun_impl(int a, float b); 
std::string fun(int a, float b) 
{ 
    return fun_impl(a, b); 
} 
std::string fun_impl(int a, float b) 
{ 
    return "Hello World!"; 
} 

請注意,這不會在MSVC中工作,但有解決方法。另外,您需要使用-DBOOST_PP_VARIADICS=1進行編譯。

0

這個宏中最後一個逗號的用途是什麼?

#define TYPEOF(x) DETAIL_TYPEOF(DETAIL_TYPEOF_PROBE x,) 

我認爲這是在最後一個逗號,並可以被編碼爲

#define TYPEOF(x) DETAIL_TYPEOF(DETAIL_TYPEOF_PROBE x) 

檢查怎麼會沒有最後一個逗號在這個宏

1工作。在DETAIL_DEFINE

STRIP((std::string)(fun)((int) a, (float) b)) --> (fun)((int) a, (float) b) 

TYPEOF((fun)((int)a, (float) b))) --> fun 

2.)第二個參數)的第一個參數在DETAIL_DEFINE

STRIP(STRIP((std::string)(fun)((int)a, (float) b))) --> ((int) a , (float) b) 

TYPEOF (((int) a , (float) b)) --> (int) a , (float) b 

3.)在DETAIL_DEFINE第三個參數

TYPEOF ((std::string)(fun)((int) a , (float) b)) --> std::string 

結果:

DETAIL_DEFINE (fun , ((int) a , (float) b), std::string) 

BTW ,對於那些老年人推動無BOOST_PP_VARIADIC_TO_SEQ使用 BOOST_PP_TUPLE_TO_SEQ這樣的:

#define BOOST_PP_VARIADIC_TO_SEQ(...) BOOST_PP_TUPLE_TO_SEQ(PP_NARG(__VA_ARGS__) , (__VA_ARGS__)) 

而且PP_NARG您可以通過google搜索找到的任何地方,那就是:

//Original Author: Unknown, but well recognized recursive variadic macro 
#define PP_NARG(...)  PP_NARG_IMPL(__VA_ARGS__,PP_RSEQ_N()) 
#define PP_NARG_IMPL(...) PP_ARG_N(__VA_ARGS__) 
#define PP_ARG_N(\ 
      _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \ 
     _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \ 
     _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \ 
     _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \ 
     _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \ 
     _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \ 
     _61,_62,_63,N,...) N 
#define PP_RSEQ_N() \ 
     63,62,61,60,     \ 
     59,58,57,56,55,54,53,52,51,50, \ 
     49,48,47,46,45,44,43,42,41,40, \ 
     39,38,37,36,35,34,33,32,31,30, \ 
     29,28,27,26,25,24,23,22,21,20, \ 
     19,18,17,16,15,14,13,12,11,10, \ 
     9,8,7,6,5,4,3,2,1,0 
+0

你爲什麼回答這樣一個老問題(用一個可接受的答案)?另外,這實際上是一個答案? – lodo 2015-03-31 18:55:34

+0

是的,這是一個很好的答案,我已經在我的項目中使用了這個解決方案,但是我在第一個宏中發現了額外的逗號#define TYPEOF(x)DETAIL_TYPEOF(DETAIL_TYPEOF_PROBE x,)最後這裏是多餘的 – 2015-04-01 15:55:00