2011-06-27 39 views
4

GCC __attribute__((pure))__attribute__((const))允許函數分別聲明爲非–副作用和引用透明;比方說,我想寫pure_assertconst_assert宏,其參數必須是嚴格的適當水平的表達,那就是:是否可以編寫這些pure_assert和const_assert宏?

assert(oops_a_side_effect()); 

默默導致不同的行爲,調試和發佈,但:

pure_assert(oops_a_side_effect()); 
const_assert(oops_read_a_global()); 

至少在調試版本中是編譯時錯誤。對於我所希望的是顯而易見的原因,你不能只創建一個pure_assert_impl宣佈__attribute__((pure))並且已經擴展到它的宏。那麼可以寫這些宏嗎?

+0

我認爲誰發明了術語「的人蔘照透明度「應該以某種方式受到懲罰。我不得不查看它,維基百科指出,當一個函數是引用透明的,那麼你可以用它的函數結果替換一個調用。仍然不清楚沒有副作用的功能區別是什麼? –

+2

一個真正的隨機數發生器(即基於硬件)不會產生副作用(調用它不會改變程序狀態;所有將來的調用仍然是真正的隨機),但它肯定不是透明的透明的(不能用其結果代替函數,因爲它不會隨機)。 「無副作用」也被稱爲「純功能」。正如WP所指出的,任何純函數或其組合都是透明的。 – MSalters

回答

2

gcc強制執行const函數不能分別調用非純函數或非const函數嗎?如果是這樣,您可以定義一個正確的屬性函數模板,它將函數指針作爲模板參數,並讓宏展開爲該函數模板的調用。我假設你需要支持帶參數的函數,這對於C++ 0x variadic模板或lambda表達式會更好。

0

運氣不好,恐怕。甚至在編譯器開始查看代碼之前,宏由預處理器進行擴展。

也許可能是是一個解決方案,是讓assert測試表達式在不考慮發佈或調試模式的情況下進行評估,但是隻能在調試模式下測試結果。

2

gcc不以任何方式強制執行純度或參考透明度。這些屬性僅僅是優化器的提示。所以答案是否定的。

1

我懷疑有這個一個非常好的解決,但我發現這樣的事情const_assert(),這出現用gcc的兩個版本我都隨手將手上的工作的可能性(4.1.2和4.4.4)。

#include <assert.h> 

extern void dummy_void_function(void); 

#define const_assert(x) \ 
    assert(__builtin_choose_expr(__builtin_constant_p((x) == (x)), \ 
     (x), dummy_void_function())) 

extern int function(void); 
extern int __attribute__((pure)) pure_function(void); 
extern int __attribute__((const)) const_function(void); 
extern int global; 
extern volatile int volatile_global; 

void test(int arg) 
{ 
    /* These cause compile-time errors: */ 
    const_assert(function() == 0); 
    const_assert(pure_function() == 0); 
    const_assert(volatile_global == 0); 

    /* These don't: */ 
    const_assert(const_function() == 0); 
    const_assert(arg == 0); 
    const_assert(global == 0); 
} 

這真是檢查表達(x) == (x)是否被視爲編譯時由編譯器常數,並創造破碎,如果不是這樣的。 「好」的情況下,有效地成爲assert(x);和壞的產生編譯時錯誤:

$ gcc -c const_assert.c 
const_assert.c: In function 'test': 
const_assert.c:18: error: void value not ignored as it ought to be 
const_assert.c:19: error: void value not ignored as it ought to be 
const_assert.c:20: error: void value not ignored as it ought to be 

然而,啓用了優化,它仍然產生錯誤的預期的情況下,但其中之一是有點奇怪:

$ gcc -O -c const_assert.c 
const_assert.c: In function 'test': 
const_assert.c:18: error: void value not ignored as it ought to be 
const_assert.c:19: error: first argument to '__builtin_choose_expr' not a constant 
const_assert.c:20: error: void value not ignored as it ought to be 

...你會期望__builtin_constant_p()的結果被視爲一個常數!所以我不知道,我真的相信這是真的代碼...

(我沒有什麼好的想法,現在的pure_assert()!)

相關問題