> > If I understand your proposal correctly, it's still a preprocessor
> > directive but it disguises itself as normal C++ code. Preprocessor
> > code and normal C++ code are essentially two independent languages.
> > The way it works at the moment is that the preprocessor runs first
> > (without it having to care about scopes or other C++ rules). The
> > actual C++ code is not parsed until after the preprocessor has
> > finished. Since they are so different I wonder if it's not a good
> > thing that they have different syntax.
> >
> I agree that they are two separate languages, but those two languages
> inhabit the same source files, and they intermingle. Because of this, I
> think that a common syntax is helpful for improving user experience by
> reducing the need to change your frame of reference given that the code can
> now look the same regardless of it is preprocessor code or regular C++
> code.

Even if it looks similar you still need to think differently.

In a regular if statements you can write normal code in the condition, but in the condition of a condexpr if statement you would only be able to use macros, literals and simple operators. My guess is that a lot of people would be confused why they cannot even call constexpr functions there.

You cannot put a regular if statement outside a function, but I guess you would want to allow condexpr if statements outside functions because otherwise you prevent the most useful applications of "conditional inclusion".

You can use #if and #ifdef anywhere, inside expressions, it doesn't matter.
I guess you could allow condexpr if statements to do the same (as long as you have no unmatched curly brackets { } inside) but it would look strange.

// Example with #ifdef
enum States
{
    start_state,
    intermediate_state,
    end_state,
#ifdef DEBUG
    debug_state
#endif
};

// Example with condexpr (how would you indent this?)
enum States
{
    start_state,
    intermediate_state,
    end_state,
if condexpr (defined(DEBUG))
{
    debug_state
}
};

Something else I also come to think about is scope...
It looks like condexpr if statements introduces a scope, but it doesn't, which is very confusing if you define variables inside there.
I guess you could define it in such a way that the opening and closing curly bracket { } of the condexpr if statement expands to opening and closing curly bracket { } in the resulting code but that would limit its usefulness a lot.