Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using constexpr to replace #define and #ifdef for conditional compilation

I am trying to replace the preprocessor #define and #if/#ifdef's that I am using to control conditional compilation with constexpr variables and ifs.

Is it possible to declare constexpr variables such that they reproduce the #defines in that they don't allocate runtime storage, and that taking the address of one leads to a compile time error?

Edited to add code example.

So in the headers I want to have something like

namespace ExampleNamespace
{
  enum class Platform : int {Darwin, Linux, Windows};

  constexpr Platform BuildPlatform = Platform::Darwin;  // Line A.
};

While in the code I want

if constexpr (Platform::Darwin == BuildPlatform)        // Line B.
  {
    cout << "Platform is Darwin" << endl;
  }
else
  {
    cout << "Platform is not Darwin" << endl;
  };

const Platform *const PlatformAddress = &BuildPlatform; // Line C.
const Platform &BuildPlatform2 = BuildPlatform;         // Line D.

Then aim is then to change the definition of BuildPlatform on Line A, such that Line B is evaluated at compile time (and the else clause gets discarded/not compiled) and lines C and D (and anything that does the same thing, or relies on runtime storage for BuildPlatform) generates a compiler error.

Is such a construct possible in C++17?

like image 688
Andy Avatar asked Nov 04 '25 02:11

Andy


1 Answers

It is partially possible:

if constexpr (Platform::Darwin == BuildPlatform) {        // Line B.
    std::cout << "Platform is Darwin" << std::endl;
} else {
    std::cout << "Platform is not Darwin" << std::endl;
}

but as template <typename T> void foo() {static_assert(false);} is ill formed, code of all branches should have some kind of validity.

#ifdef (DarwinPlatform) // constexpr cannot be used here, you have to 
                        //rely on MACRO here
# include <darwin.h>     // Some OS specific header
#endif

void foo()
{
    if constexpr (Platform::Darwin == BuildPlatform) {
        DarwinMethod(); // Won't compile on other platforms as
                        // the method doesn't exist.
        // you should make the block template with template dependent code
        // to allow code to compile.
        // as http://coliru.stacked-crooked.com/a/c695575e4dcdecee
    }
}
like image 153
Jarod42 Avatar answered Nov 06 '25 18:11

Jarod42