2015-12-09 87 views
0

這是我想怎樣做:一個constexpr函數可以調用一個返回void的函數嗎?

void g() { 
    std::cout << "smth1" << std::endl; 
    std::cout << "smth2" << std::endl; 
} 

constexpr bool f() {return g(), true;} 

編譯器(gcc版本4.8.2)是不滿意這一點,因爲gconstexpr。是否有可能解決這個問題?

+8

在編譯時評估過程中,您會希望調用帶有某種副作用的函數(在這種情況下會產生輸出)嗎? – 5gon12eder

+0

@ 5gon12eder當我寫'if(f()){...},我希望編譯器在優化階段擺脫那個分支,因爲f()在編譯時保證返回true。 – AlwaysLearning

+0

@AlwaysLearning所以你希望編譯器執行'g'的副作用但是消除分支? –

回答

3

constexpr的要點是它可以在編譯時完全擴展。編譯器不可能將運行時副作用(使用cout)放入實際上更復雜的編譯時常量中。換句話說:在運行時,沒有實際的函數調用會對constexpr函數產生影響!

幸運的是,解決方案很簡單!

變化fconstexpr bool f() { return true;}

和你有條件的:

g(); 
if(f()) 
{ 
    // ... 
} 
+0

就我而言,'g'是一個模板參數。我想讓'g'返回'void'或'bool'。我在'g'的返回類型上標記分派。我展示的代碼是用於'g'返回'void'的情況。當'g'返回'bool'時,我返回'g()',然後在條件語句中使用它。當'g'返回'void'時,我想避免分支。 – AlwaysLearning

+0

答覆確實回答了問題,因此被接受。我會問另一個問題,將提供所有相關的細節。 – AlwaysLearning

+0

這是它:http://stackoverflow.com/q/34186365/2725810 – AlwaysLearning

0

一個常量表達式的評估過程中被調用函數的任何計算不能有任何副作用。在C++ 11中,規則實際上要嚴格得多,只允許一個return語句作爲函數體,但與這個問題無關。

編譯器無權刪除constexpr函數中的任何代碼以使其符合要求。首先不要寫這樣的代碼是你的責任。

但是,如果靜態評估過程中的控制流程永遠不會通過它,那麼在constexpr函數中使用具有副作用的代碼是可以的。

這是有效的C++ 11。

void g() { std::cout << "hello, world" << std::endl; } 
constexpr bool f(const bool p = false) { return p ? (g(), false) : true; } 

而且你可以這樣稱呼f

constexpr auto x = f(); // ok 

因爲p在編譯時是false,編譯器可以不需要計算調用g。在運行時,您可以使用任一參數調用f,就像它不是constexpr函數一樣。

f(false); // ok 
f(true); // ok, produces output at run-time 

你不能做什麼與設置爲true參數常量表達式進行評估。

constexpr auto x = f(true); // compile-time error 

當然,這個例子是人爲的超越任何限制,你只要簡單地寫

constexpr bool f() noexcept { return true; } 

或使用可變

constexpr auto toggle = true; 

,如果這是你所需要的。

相關問題