“constexpr if” vs “if” with optimizations - why is “constexpr” needed?

有些话、适合烂在心里 提交于 2019-11-26 14:18:45

问题


C++1z will introduce "constexpr if" - an if that will have one of branches removed, based on the condition. Seems reasonable and useful.

However, is it not possible to do without constexpr keyword? I think that during compilation, compiler should know wheter condition is known during compilation time or not. If it is, even the most basic optimization level should remove unnecessary branch.

For example (see in 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 explorer shows, that even gcc-4.4.7 with -O0 did not compile "return 1", so it achieved what was promised with constexpr if. Obviously such old compiler will not be able to do so when condition is result of constexpr function, but fact remains: modern compiler knows whether condition is constexpr or not and doesn't need me to tell it explicitly.

So the question is:

Why is "constexpr" needed in "constexpr if"?


回答1:


This is easy to explain through an example. Consider

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

and

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

Invoking

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

will trigger a compilation error (wandbox example), because both branches of the if statement have to be well-formed.

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{});
    ^

Changing pet to use 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(); }
}

only requires the branches to be parseable - only the branch that matches the condition needs to be well-formed (wandbox example).

The snippet

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

will compile and work as expected.



来源:https://stackoverflow.com/questions/40972666/constexpr-if-vs-if-with-optimizations-why-is-constexpr-needed

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!