"constexpr if"vs"if"with optimizations - 为什么需要"constexpr"?

Mat*_*szL 39 c++ constexpr c++17 if-constexpr

C++ 1z将引入"constexpr if" - 如果将根据条件删除其中一个分支.似乎合理有用.

但是,没有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;
    }
}
Run Code Online (Sandbox Code Playgroud)

Godbolt探险家表示,即使是带有-O0的gcc-4.4.7也没有编译"返回1",所以它实现了constexpr所承诺的.显然,当条件是constexpr函数的结果时,这样的旧编译器将无法这样做,但事实仍然存在:现代编译器知道条件是否为constexpr,并且不需要我明确地告诉它.

所以问题是:

为什么"constexpr if"需要"constexpr"?

Vit*_*meo 50

这很容易通过一个例子来解释.考虑

struct Cat { void meow() { } };
struct Dog { void bark() { } };
Run Code Online (Sandbox Code Playgroud)

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

调用

pet(Cat{});
pet(Dog{});
Run Code Online (Sandbox Code Playgroud)

将触发编译错误(wandbox示例),因为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{});
    ^
Run Code Online (Sandbox Code Playgroud)

更改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(); }
}
Run Code Online (Sandbox Code Playgroud)

只需要分支是可解析的 - 只有匹配条件的分支才需要格式良好 (wandbox示例).

片段

pet(Cat{});
pet(Dog{});
Run Code Online (Sandbox Code Playgroud)

将按预期编译和工作.

  • 谢谢."可解析"和"格式良好"之间的区别在我之前躲过了:-) (2认同)