3

Which one is more appropriate for compile-time configurations (such as debug/release), preprocessor directives, or if constexpr?

#define DBG

#if DBG
// some code
#endif

// --------------------------------- or

inline constexpr bool DEBUG { true };

if constexpr ( DEBUG )
{
// some code
}
digito_evo
  • 3,216
  • 2
  • 14
  • 42
  • 1
    I use `NDEBUG` to be compatible with `assert`. – Bathsheba Apr 08 '22 at 12:55
  • 1
    `if constexpr` ensures the disabled code is still syntactically correct – Alan Birtles Apr 08 '22 at 12:56
  • to understand this concept first you need to have a look at how c++ code runs under the hood . c++ compiler compile `preprocess directives` first. `#if` is mostly used to turn on and off some code functionality like checking c++ version `#if __cplusplus <201103L // do some thing #endif` – zain ul din Apr 08 '22 at 12:58
  • @AlanBirtles: It also _requires_ that the disabled code is still syntactically correct. This might not always be the case. – MSalters Apr 08 '22 at 13:02
  • @MSalters are you sure? it might not be semantically correct, it might not compile but the syntax must be correct? In what cases would it allow syntax errors? – Alan Birtles Apr 08 '22 at 13:16
  • @AlanBirtles: Consider a `struct` which in debug builds has a checksum added. As you correctly state, `if constexpr(debug)` code must still be syntactically correct in release builds. So you can't use `if constexpr(debug)` to verify that checksum in debug builds, since the checksum doesn't exist in release builds. Put the checksum validation inside an `#ifndef NDEBUG`, and it doesn't matter in release builds. – MSalters Apr 08 '22 at 13:28
  • @MSalters I still don't see what you're getting at, the code must still be syntactically correct? You said that wasn't always true? – Alan Birtles Apr 08 '22 at 13:35
  • 1
    @AlanBirtles: Matter of perspective. I assumed that the code to be disabled was a given, and the question was how to disable it. In that perspective, you end up with that observation: "`if constexpr` requires that disabled code is still syntactically correct", so you might need `#if` when the requirement for `if constexpr` is not met. – MSalters Apr 08 '22 at 13:40

2 Answers2

2

You still generally need #if for this. #if can do things like change what headers you are including, change what functions and types are defined, and change the definitions of other preprocessor directives. if constexpr cannot do any of that.

0x5453
  • 12,753
  • 1
  • 32
  • 61
  • "change what functions and types are defined" can be done indirectly with `using f = f_impl` though. – MSalters Apr 08 '22 at 13:31
2

Note that, if if constexpr is not part of a template, then the other parts of the if (such as the elses) are still compiled and checked for validity.

From cppreference:

If a constexpr if statement appears inside a templated entity, and if condition is not value-dependent after instantiation, the discarded statement is not instantiated when the enclosing template is instantiated .

Outside a template, a discarded statement is fully checked. if constexpr is not a substitute for the #if preprocessing directive:

ChrisMM
  • 8,448
  • 13
  • 29
  • 48
  • So is it bad practice/problematic for such a use case? – digito_evo Apr 08 '22 at 13:05
  • @digito_evo I think that would depend on the use case. The compiler will likely optimize it away, but if the code in the "else" is not valid, then it will still fail to compile. I tend to prefer the constexpr version, and always use them with templates, but I use the preprocessor version if I need to disable code that won't compile under certain preprocessor definitions. – ChrisMM Apr 08 '22 at 14:18
  • 1
    Also even if it is part of a template, the discarded statement is still checked, it's just that it's not checked as thoroughly as in the other case. [Example here](https://godbolt.org/z/Gaoqs41xh). – Nathan Pierson Apr 08 '22 at 16:08