2016-12-05 72 views
28

C++ 1z將引入「constexpr if」 - 根據條件,如果將刪除其中一個分支。看起來合理而有用。「constexpr if」vs「if」如何優化 - 爲什麼需要「constexpr」?

但是,沒有constexpr關鍵字是不可能的?我認爲在編譯期間,編譯器應該知道在編譯期間是否知道情況是否已知。如果是這樣,即使是最基本的優化級別也應該刪除不必要的分支。

例如(見godbolt:https://godbolt.org/g/IpY5y5):

int test() { 
    const bool condition = true; 
    if (condition) { 
     return 0; 
    } else { 
     // optimized out even without "constexpr if" 
     return 1; 
    } 
} 

Godbolt資源管理器顯示,即使是GCC-4.4.7用-O0沒有編譯 「返回1」,所以它取得的成就與承諾constexpr如果。很顯然,當條件是constexpr函數的結果時,這樣的舊編譯器將不能這樣做,但事實仍然是:現代編譯器知道條件是否爲constexpr,並且不需要我明確地告訴它。

所以,問題是:

爲什麼需要在 「constexpr如果」 「constexpr」?

+7

這不僅是一個優化的事情:一個'constexpr if'的枯枝被允許是無效的,也就是說,它不會對自己的編譯。雖然你的問題顯示。 – Quentin

回答

38

這很容易通過一個例子來解釋。考慮到良好形成

struct Cat { void meow() { } }; 
struct Dog { void bark() { } }; 

template <typename T> 
void pet(T x) 
{ 
    if(std::is_same<T, Cat>{}){ x.meow(); } 
    else if(std::is_same<T, Dog>{}){ x.bark(); } 
} 

調用

pet(Cat{}); 
pet(Dog{}); 

會觸發一個編譯錯誤(wandbox example),因爲if語句的兩個分支都有。

prog.cc:10:40: error: no member named 'bark' in 'Cat' 
    else if(std::is_same<T, Dog>{}){ x.bark(); } 
            ~^
prog.cc:15:5: note: in instantiation of function template specialization 'pet<Cat>' requested here 
    pet(Cat{}); 
    ^
prog.cc:9:35: error: no member named 'meow' in 'Dog' 
    if(std::is_same<T, Cat>{}){ x.meow(); } 
           ~^
prog.cc:16:5: note: in instantiation of function template specialization 'pet<Dog>' requested here 
    pet(Dog{}); 
    ^

更改pet使用if constexpr

template <typename T> 
void pet(T x) 
{ 
    if constexpr(std::is_same<T, Cat>{}){ x.meow(); } 
    else if constexpr(std::is_same<T, Dog>{}){ x.bark(); } 
} 

只需要分支是解析的 - 只有符合條件需要很好地形成(wandbox example)分支。

的片段如預期

pet(Cat{}); 
pet(Dog{}); 

將編譯和工作。

+1

謝謝。 「解析」和「格式良好」之間的區別在我之前避開了:-) – MateuszL