1

From the description on cppreference I assumed that if constexpr would behave like a normal if but works at compile time.

The description says:

In a constexpr if statement, the value of condition must be a contextually converted constant expression of type bool. If the value is true, then statement-false is discarded (if present), otherwise, statement-true is discarded.

constexpr (false) is obviously false, so the static_assert should be discarded, right? However, with the following code I always get a compilation error for the assertion:

if constexpr (false) {
  static_assert(false, "empty");
}

while I expected no compile error. This is XCode 10 with clang and C++17 enabled. Is that a problem of the compiler or is it me misunderstanding this concept?

By request (even though I think it's not relevant here): the compiler error I get is:

Static_assert failed "empty"

Mike Lischke
  • 48,925
  • 16
  • 119
  • 181
  • The static_assert is not ill-formed. – Mike Lischke Apr 30 '19 at 13:36
  • 1
    "I always get a compilation error" - *What* error? Please, always include the text of any error messages in the question (verbatim). – Jesper Juhl Apr 30 '19 at 13:37
  • 2
    When reading the reference did you happen to read "*Outside a template, a discarded statement is fully checked. if constexpr is not a substitute for the #if preprocessing directive"* – StoryTeller - Unslander Monica Apr 30 '19 at 13:38
  • 2
    @MikeLischke `static_assert(false, ...);` is considered ill-formed: *"If the value of the expression when so converted is true, the declaration has no effect. Otherwise, the program is ill-formed"* http://www.eel.is/c++draft/dcl.dcl#6 – Holt Apr 30 '19 at 13:38
  • 1
    consider the example from cppref that starts with "Outside a template, a dscarded statement is fully checked." – 463035818_is_not_an_ai Apr 30 '19 at 13:38
  • 1
    In addition to the dupe, `static_assert(false, "")` is always ill-formed, no matter if it's in a template or not. – Guillaume Racicot Apr 30 '19 at 13:38
  • @JesperJuhl The error is what I wrote: the compiler error for the assertion, as if there was no `if constexpr (false)` part. – Mike Lischke Apr 30 '19 at 13:43
  • 1
    @MikeLischke That's not the error message. That is you paraphrasing the error message. What I was trying to say was: please always include *the exact, unmodified, text* of any error messages in the question. Just the way the compiler spits it out. I *get* what the error is in this case. I was just trying to provide some general advice. – Jesper Juhl Apr 30 '19 at 13:46
  • 1
    I added another duplicate that explains how `static_assert(false, "")` won't compile even if not instantiated. – Guillaume Racicot Apr 30 '19 at 13:49

1 Answers1

4

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.


From the same page you linked:

Note: the discarded statement can't be ill-formed for every possible specialization:

template <typename T>
void f() {
     if constexpr (std::is_arithmetic_v<T>)
         // ...
     else
       static_assert(false, "Must be arithmetic"); // ill-formed: invalid for every T
}

And that static_assert(false, ...) is a compilation failure for every possible specialization, so that static_assert always fires, even if the branch would be discarded.

Community
  • 1
  • 1
iBug
  • 35,554
  • 7
  • 89
  • 134
  • From the description it is not clear that `if constexpr` only works in templates. There's even another non-templated example (with that not-defined variable x). – Mike Lischke Apr 30 '19 at 13:44
  • @MikeLischke This answer doesn’t claim that `if constexpr` only works in templates. It just says that the discarded branch mustn’t be unconditionally ill-formed (and `static_assert(false)` is by definition ill-formed). – Konrad Rudolph Apr 30 '19 at 13:45
  • Well, the answer only speaks about templates and ill-formedness for every possible specialization, which leads to the conclusion this only can work with templates. Could you please add a valid use of `if constexpr`, which does not appear in a template? That would help me to understand this better and I'd accept your answer. – Mike Lischke Apr 30 '19 at 13:51
  • @MikeLischke As said by others - whether it's in a template doesn't matter. What matters is that the "false branch" can't be unconditionally ill-formed. – iBug Apr 30 '19 at 13:53
  • 1
    @MikeLischke Or more precisely, `static_assert(false)` cannot appear in a *constexpr if* statement. – iBug Apr 30 '19 at 14:15