1

I have been reading about using constexpr instead of using macros for better safety, as macros can lead to undefined behavior. However, if I have the code in the following example, is it okay to do this, and just use preprocessor if statements (#if), or should I change the macros to constexpr bool.

Here is what I wanted to do:

#if NDEBUG
#define ENABLE_VALIDATION_LAYERS 0
#else
#define ENABLE_VALIDATION_LAYERS 1
#endif

vs

#if NDEBUG
constexpr bool enable_validation_layers = false;
#else
constexpr bool enable_validation_layers = true;
#endif

Code usage right now looks like this:

//if validation layers are not enabled, the validation support does not need to be checked
#if ENABLE_VALIDATION_LAYERS
        if (!CheckValidationLayerSupport()) //function that returns a bool to check if validation layers are supported
        {
            throw std::runtime_error("validation layers requested, but not available!");
        }
#endif
raf_k
  • 19
  • 1
  • The first is conditional compilation. If ENABLE_VALIDATION_LAYERS is 0 the code inside the `#if` is completely removed by the preprocessor. – Retired Ninja May 09 '21 at 06:23
  • 7
    What macros are they talking about that lead to undefined behavior? Macros that can be replaced with `constexpr`s probably should not be an issue, function-like macros are where things get messy. Then again, modules pose a threat to macro constants too, but that's still not undefined behavior. – mediocrevegetable1 May 09 '21 at 06:25
  • @mediocrevegetable1 throughout my research, people say to use constexpr in places where the macro acts more like a variable. Such as saying constexpr int width = 600; rather than #define WIDTH 600. – raf_k May 09 '21 at 06:31
  • @raf_k If people are saying "Macro bad" with no reason whatsoever as to why, that's pretty weird. Please, if you can, go back to these people if possible and ask them _why exactly_ macro constants should not be used and why using them is "undefined behavior". – mediocrevegetable1 May 09 '21 at 06:50
  • 2
    Replacing `#define foo 1` with `constexpr int foo = 1;` is general good advice. The example you gave in the question though is not the same thing at all. There are very good reasons to completely remove code that is not intended to be in a release build that way. – Retired Ninja May 09 '21 at 06:54
  • You may be confused because conditional compilation is not discouraged in the same way that #defining value literals as constants is discouraged. – Patrick Parker May 09 '21 at 07:02
  • 1
    However there are still valid reasons why someone may wish to avoid maintaining latent dead code walled off by preprocessor defines. – Patrick Parker May 09 '21 at 07:06
  • @PatrickParker If there was a drinking game where you had to drink every time you saw `#if 0` and a bunch of random code then some of my old bosses code would be deadly. – Retired Ninja May 09 '21 at 07:10
  • 2
    @mediocrevegetable1 macros can lead to hard to track problems. If you use a “macro constant” in an inline function, and if for some reason the value of that macro changes for that inline function in different compilation units, then the code will compile, but you will encounter undefined behavior. And finding such an error is not an easy task. So if you can replace a preprocess or macro with c++ code then you generally should do so. – t.niese May 09 '21 at 07:46
  • It depends the `constexpr` can be secluded to a scope while macro doesn't understand c++ semantics. Everywhere you put that macro c++ compiler will expand it so it may break your program. That is the reason why `constexpr` is preferred. – AllMightyGoat May 09 '21 at 10:29
  • Does this answer your question? [What is the difference between a macro and a const in C++?](https://stackoverflow.com/questions/6393776/what-is-the-difference-between-a-macro-and-a-const-in-c) – Patrick Parker May 11 '21 at 06:25

0 Answers0