2012-11-08 27 views
11

同時瀏覽constexpr上的一箇舊問題我偶然發現了一個非常重要的評論。 基本上它歸結爲: (這是合法的C++ 11 :()爲什麼constexpr適用於不純的功能

constexpr double f(bool b) 
{ 
return b? 42:42/(rand()+1); // how pure is rand ;) 
} 

我的問題是什麼,這是標準允許的原因因爲即時通訊引用透明的忠實粉絲,我希望。他們有一個很好的理由:),我想知道它。

順便說一句,有相關的Q,但大多數A甚至不提及純粹的事情,或者當他們做他們沒有指定爲什麼std允許這個推理。 Relation between constexpr and pure functions

+1

rand()是一個constexpr? – Yakk

+1

不,它不是,這就是爲什麼我把;)在評論 – NoSenseEtAl

回答

7

在函數定義關鍵字constexpr告訴該功能可以在編譯時,如果所有的參數和變量在編譯時知道自己執行的編譯器。然而,沒有這樣的保證,例如當在運行時可以知道一些值,在這種情況下該功能將在運行時被執行。

然而,它無關不純,因爲這些條款意味着輸出取決於輸入唯一的,無論你有多少次調用函數的輸入參數相同的值,每次輸出都是相同的,而不管它是在編譯時還是運行時計算的。

實施例,

constexpr int add(int a, int b) { return a + b; } //pure! 

const int a = 2, b = 3; //const 
int c = 2, d = 3;  //non-const 

//we may read update c and d here! 

const int v1 = add(2,3); //computed at compile-time 
const int v2 = add(a,3); //computed at compile-time 
const int v3 = add(2,b); //computed at compile-time 
const int v4 = add(a,b); //computed at compile-time 

const int v3 = add(c,3); //computed at runtime 
const int v3 = add(c,b); //computed at runtime 
const int v3 = add(a,d); //computed at runtime 
const int v3 = add(c,d); //computed at runtime 

注意,這裏add爲純函數不論它是在編譯時或運行時計算的。

+1

任何純函數可以在編譯時按as-if規則進行評估,而不考慮constexpr。這就是所謂的不斷摺疊。在你的例子中'constexpr'似乎沒有任何區別。 – Potatoswatter

+1

@Patatoswatter:你的意思是我們可以寫'std :: array a;'即使'add'不是'constexpr'?我不這麼認爲。 – Nawaz

+1

我的意思是你的例子:v)。 (你的答案似乎沒有解決常量表達式上下文。)我[打開一個問題](http://stackoverflow.com/questions/14472359/why-do-we-need-to-mark-functions-as -constexpr?lq = 1)關於是否std :: array '會是一件壞事。 – Potatoswatter

6

因爲對於某些輸入參數域,不會採用不純的路徑。對於那個域名,constexpr會正常工作。

例如,你的函數可能有一個簡單的分支和一個更復雜的分支。你可以指定你的函數可以在常量表達式中使用,函數參數必須滿足這個條件,並且符合這個條件,從而得到函數中總是純粹的簡單分支。

這是一個有用的副作用是,您可以在常量計算過程中導致錯誤。也就是說,如果違反了簡單分支中的前提條件,您可能會導致對不純表達式的評估,從而引發編譯時錯誤(在這裏,斷言或異常是一個好主意,因爲它繼續投訴函數在運行時環境)。

9

在標準中,相關要求被埋在constexpr功能要求的主要清單之下。它在§7.1.5/ 5:

對於constexpr功能,如果存在,使得函數調用取代會產生一個常量表達式(5.19),是形成不良的程序中沒有的功能的參數值;不需要診斷。

§5.19定義了常量表達式的要求,因此您不能調用rand()

寬鬆的限制允許您有條件純的功能。您的示例f(true)是有效的模板參數,但f(false)不是。

不利的一面是,編譯器不會驗證constexpr函數是否可以實際用於其預期用途。你需要編寫測試用例。

啊,litb的回答也是正確的。 (但是這個更簡單。)

+1

這是正確的答案。 – Omnifarious

+1

這也是一個更好的答案,因爲它引用了標準的相關部分,並對它的含義給出了很好的解釋。 – Omnifarious

相關問題