6

Why is this code giving error while compiling? My knowledge (and also this) of "if constexpr" says the else block shouldn't get compiled.

if constexpr (true) {
    int a = 10;
} else {
    int b = 10
}

The error is:

error: expected ‘,’ or ‘;’ before ‘}’ token

Compiler used: g++ version 7.5.0
While compiling I used -std=c++17 flag.

P.S. The missing ';' is intentional, just to check whether else is being compiled or not.

cigien
  • 57,834
  • 11
  • 73
  • 112
  • 2
    Maybe you should make it explicit that the missing ```;``` is purposeful; at least that seems to be your intention to me (to test if the ```else``` block is being compiled I presume). – User 10482 Aug 18 '20 at 13:28
  • 1
    There is a world of difference between "doesn't get compiled" (or instantiated) and "doesn't parse". – Eljay Aug 18 '20 at 13:58
  • 1
    This is a perfectly reasonable question, and the intent of the code snippet is clear. – cigien Aug 18 '20 at 22:47

1 Answers1

11

There are 2 separate, but related issues here.

Firstly, if constexpr will only conditionally compile a branch within a template. Outside of a template, all branches will be compiled and must be well formed.

Secondly, even in a template, the discarded branch of an if constexpr can't be ill-formed for all possible instantiations. This is not the case in your code, since:

int b = 10

is always ill-formed (due to the missing ;).

So the compiler is correct in giving a compile error. Technically, if the discarded branch is ill-formed for all instantiations, then the compiler is not required to give a compiler error, but the code is still wrong.

cigien
  • 57,834
  • 11
  • 73
  • 112
  • Thanks for the quick answer. Can you explain a bit more on "within a template"? – ImaginationIsPower Aug 18 '20 at 13:20
  • Also, the second case is NDR. – T.C. Aug 18 '20 at 13:21
  • 1
    @KishanShukla `if constexpr` behave a bit like a template. The false branch is still compiled, but not always instantiated. If there is no dependent types, then all branched are checked for validity. This is not like the preprocessor. – Guillaume Racicot Aug 18 '20 at 13:21
  • @KishanShukla See the [ref](https://en.cppreference.com/w/cpp/language/if). There is an example where it shows that the `if constexpr` needs to be dependent on `T` inside a `template` for one of the branches to be discarded. – cigien Aug 18 '20 at 13:25
  • 1
    @T.C.: Is it really? It doesn’t even *parse*, so I’m not sure we reach the level of analysis that “checks” for a possible instantiation. – Davis Herring Aug 18 '20 at 13:36
  • @DavisHerring Last time I checked we still allow token soup implementations. – T.C. Aug 18 '20 at 14:34
  • @T.C.: Lacking a definition for instantiation, I can’t say whether the bad syntax should be part of it. The grammar certainly “sees” into everything even if it’s a known implementation technique to match only `{…}` in that circumstance. – Davis Herring Aug 18 '20 at 14:36
  • 1
    @DavisHerring [temp.res]/8 has an equally non-parsing example. /shrug – T.C. Aug 18 '20 at 14:37
  • Yeah, it says `void g(T t) { +; }` *may* be diagnosed, so it doesn't seem to be required, even if parsing would fail. – cigien Aug 18 '20 at 14:40
  • 1
    The missing semi colon likely causes compilation to fail as early as during the [lexing](https://en.wikipedia.org/wiki/Lexical_analysis) stage or right after it. At that point the expression in the `if` clause didn't have a chance to be run. – bitmask Aug 19 '20 at 04:42