2012-04-20 65 views
1

我有這樣一個宏(它是從一個實際有用的用例來了,但我一直在用簡單的情況下打):功能綁定操作

#define MY_MACRO(M) M(3) M(5) M(7) 
#define MULTIPLY_BY_2(A) (2*A) 

然後我就可以寫

MY_MACRO(MULTIPLY_BY_2) 
// -> (2*3) (2*5) (2*7) 

酷!我想要的是:

#define MULTIPLY(A,B) (A*B) 
MY_MACRO(BIND(MULTIPLY, 2)) 

獲得與上面相同的結果。 BIND可能是什麼?我嘗試了一些黑客,並可以報告這幾乎是可能的(我覺得很驚奇)。但它不漂亮,而且不是一般的。這可以做以及? (即純粹在CPP中建立一些真正的功能性設施?)它可以做得足夠好來綁定綁定宏嗎?

也許我真正要問的是在任何你知道的預處理庫中是否有像這樣的工具?在Boost中我沒有發現任何相似的東西。

+3

嘗試對預處理器做太多的操作可能會使代碼成爲未來調試/理解的噩夢。 – 2012-04-20 23:04:49

+1

Boost是基於Vesa Karvonen的工作,它顯然在預處理器中實現了一個完整的函數式語言,包括詞法環境,尾遞歸等。所以我對「在Boost中找不到這樣的東西」持懷疑態度。你確定?不過,不太可能在這種漂亮而簡單的部分應用語法下。 – Kaz 2012-04-20 23:06:01

回答

4

你不能要求宏編程很漂亮,對不起。

+2

美在眼前。但是,好吧,忘記「美麗」,讓我們留在「一般」。像預處理器BIND可以實現一般工作嗎? Boost-Preprocessor庫中有這樣的事情嗎? – 2012-04-21 14:07:01

1

我不知道,我完全理解你想實現什麼樣的功能,但以下適合您的例子:

#define MULTIPLY_2(X) (2*(X)) 
#define POW_2(X) ((X)*(X)) 
#define BIND(OP, NUM) OP ## _ ## NUM 

MULTIPLY_2 &有限公司手錶,你總是把括號周圍參數是確定這有您想要的評估訂單。同時也要注意,與您一般的策略參數可能會多次評估,如果表達式包含副作用,這可能是一個嚴重的錯誤。

更好的辦法是有你的基本操作如內聯函數和組成與宏函數調用

#define MULTIPLY_2(X) multiply2(X) 
#define POW_2(X) pow2(X) 
+0

有趣的想法,但不,數字的簡單例子只是一個例子;在現實中,我可能需要綁定一個字符串或artibtrary表達式(而不是文字2)。 – 2012-04-21 14:05:17

2

不平衡括號可以做一個排序綁定操作的,但隨後的調用語法是一個正常的不同宏。它需要一個額外的關閉paren。

#define BIND(op, arg) op (arg, 
#define MULTIPLY(a, b) ((a) * (b)) 

#define MULTIPLY_BY_2 BIND(MULTIPLY, 2) 

MULTIPLY_BY_2(5)) // note two close parens 

http://ideone.com/EQvs2

你可以嘗試定義多個宏生成密切括號適當的,但有可能是一個更好的解決方案。

1

其實,是的。在Order library,你可以表達上述這樣的:

#include <order/interpreter.h> 

#define ORDER_PP_DEF_8my_mac ORDER_PP_FN(\ 
8fn(8M, 8seq(8ap(8M, 3), 8ap(8M, 5), 8ap(8M, 7)))) 

#define ORDER_PP_DEF_8bind ORDER_PP_FN(\ 
8fn(8F, 8A, 8fn(8X, 8ap(8F, 8A, 8X)))) 

#define ORDER_PP_DEF_8multiply ORDER_PP_FN(\ 
8fn(8L, 8R, 8times(8L, 8R)))  // (already built-in as 8times) 

ORDER_PP (
    8my_mac(8bind(8multiply, 2)) // -> (6)(10)(14) 
) 

,隨着bindmultiply手動定義的;爲了還支持ML-樣式的局部評價本身,所以你可以這樣寫:

ORDER_PP (8my_mac(8times(2))) // -> (6)(10)(14) 
從C預處理器帶來的略微怪異的語法

除此之外,語言基本上是一個相當簡單的Lisp/ML混合動力與許多支持常見的功能性成語。