C++ if constexpr using a constexpr bool equivalent to plain if?

152 Views Asked by At

Are the follow snippets functionally equivalent given the conditional variable that's being checked has been marked as constexpr?

Additionally, is this a correct usage of if constexpr or is it's intended application within a templatized context.

constexpr bool kOn = false;

// Snippet 1
if (kOn) { return true; }

// Snippet 2
if constexpr (kOn) { return true; }
2

There are 2 best solutions below

5
On BEST ANSWER

No, the two ifs are not equivalent.

The 1st one is evaluated at runtime, and code in both of its branches must be well-formed at compile-time.

The 2nd one is evaluated at compile-time, and code in its unused branch can be ill-formed since its dead code that gets removed by the compiler.

if constexpr is not dependent on templates.

1
On

When you use if constexpr, the branch not taken (the else if the condition was true or the first statement if the condition was false) becomes a discarded statement and gains exactly 3 "special powers".

  • If it is in a template and the condition was value-dependent (e.g., if constexpr (B) where you had a template-head template<bool B>), the discarded branch isn't instantiated at all when the specialization is instantiated.

  • Entities inside a discarded branch are still odr-used but do not require a definition:

    int x();
    int main() {
        if constexpr (false) x();  // Does not require a definition of x
        if (false) x();  // Requires a definition of x
    }
    
  • Return statements in a discarded branch do not affect auto type deduction:

    auto f() {
        if constexpr (false) return 0;
        return 0L;
    }  // OK: auto deduced as long
    
    auto g() {
        if (false) return 0;
        return 0L;
    }  // Error: two return statements with different types.
    

And, of course, the difference that if (x) doesn't force x to be a constant expression, whereas if constexpr (x) does.

So in a non-template context, there isn't much difference with your constexpr bool kOn = false;. The compiler will still check both branches to see if they compile with an if constexpr.