Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is "if constexpr" useful outside of templates?

I'm trying to understand if constexpr fully.

I understand, that if if constexpr(expr) used in a template, and expr is dependent on a template parameter, then during instantiation, only one of the then/else branches will be instantiated, the other will be discarded.

I've got two questions:

  • Is it true, that if expr is not dependent on a template parameter, then no branches of if constexpr(expr) will be discarded? If yes, where does the standard say so? I don't see where the standard has the exception that discard happens only when expr is dependent.
  • Is if constexpr useful outside of templates? If yes, what are the use cases of this? Can you give some examples to understand its usefulness?
like image 711
geza Avatar asked Dec 02 '18 23:12

geza


People also ask

What does if Constexpr do?

Constexpr if If the value is true, then statement-false is discarded (if present), otherwise, statement-true is discarded.

What is false Constexpr?

Short answer: static_assert(false) should never appear in a constexpr if expression, regardless of whether it's in a template function or whether it's in the discarded branch.


1 Answers

Is it true, that if expr is not dependent on a template parameter, then no branches of if constexpr(expr) will be discarded? If yes, where does the standard say so? […]

Yes, that is true. You're looking for [stmt.if]/2. Specifically this part:

[…] During the instantiation of an enclosing templated entity, if the condition is not value-dependent after its instantiation, the discarded substatement (if any) is not instantiated. […]

The best example I could find for a case where you would end up being value-dependent after instantiation is the one given by cppreference.com:

template<class T> void g() {
    auto lm = [](auto p) {
        if constexpr (sizeof(T) == 1 && sizeof p == 1) {
           // this condition remains value-dependent after instantiation of g<T>
        }
    };
}

Is if constexpr useful outside of templates? If yes, can you give some examples to understand its usefulness?

While all branches will be instantiated when the if constexpr does not appear inside of a template, [basic.def.odr]/10 still applies:

Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program outside of a discarded statement; […]

emphasis mine. That effectively means that an odr-use of an entity in a discarded statement doesn't count. For example:

void blub();

constexpr bool use_blub = false;

void f()
{
    if constexpr (use_blub)
    {
        blub();
    }
}

The call to blub() will not require that your program have a definition of blub() if the condition is false. Using a normal if, the program would still be required to provide a definition of blub() somewhere, even if it is never used. So you could, e.g., use if constexpr to toggle between calling some library function and calling some fallback implementation depending on whether the library is available (and being linked to). Apart from that, hypothetically, a compiler might not warn about unreachable code if it is unreachable due to an if constexpr like it potentially would with a normal if. I couldn't come up with an example of this using any actual compiler, however…

like image 102
Michael Kenzel Avatar answered Oct 23 '22 03:10

Michael Kenzel