2016-12-05 121 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