Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using constexpr if instead of macros when writing platform dependent code?

Tags:

c++

c++17

Now that if constexpr is part of C++17, is it a good replacement for macros when writing platform dependent code and similar?

I'm wondering, because I really do not like macros, and would like to use them only for include guards and includes.

// those variables should be given by the compiler
constexpr unsigned int __os = 0x1; // current os
constexpr unsigned int __os_win = 0x1; // Windows
constexpr unsigned int __os_linux = 0x2; // Linux-flavors
constexpr unsigned int __os_apple = 0x4; // Mac os

void print_os() {
    if constexpr (__os == __os_win)
        std::cout << "You're on Windows!\n";
    else if constexpr (__os == __os_linux)
        std::cout << "You're on a Linux OS!\n";
    else if constexpr (__os == __os_apple)
        std::cout << "You're on Mac OS!\n";
}

instead of the current solution:

void print_os() {
#ifdef _WIN32
    std::cout << "You're on Windows!\n";
#elif __linux__
    std::cout << "You're on a Linux OS!\n";
#elif __APPLE__
    std::cout << "You're on Mac OS!\n";
}

Both ways do not generate code for the other platforms when compiled, so they are technically the same, and as such, I would prefer the constexpr way (if it were possible).

Would this be a feasible request for compilers to implement the constexpr variables from above? I couldn't find any feature request and implementation for both gcc and clang, so there must be a reason why they don't want to implement the first way. Why is that so?

like image 522
Rakete1111 Avatar asked Mar 04 '17 14:03

Rakete1111


People also ask

When to use #define vs constexpr?

#define directives create macro substitution, while constexpr variables are special type of variables. They literally have nothing in common beside the fact that before constexpr (or even const ) variables were available, macros were sometimes used when currently constexpr variable can be used.

Is constexpr a macro?

constexpr is a new C++11 keyword that rids you of the need to create macros and hardcoded literals.

What does if constexpr do?

constexpr if can be used to replace several tricks that were already done: SFINAE technique to remove not matching function overrides from the overload set. you might want to look at places with C++14's std::enable_if - that should be easily replaced by constexpr if . Tag dispatch.

What is false constexpr?

In a constexpr if statement, the value of condition must be a contextually converted constant expression of type bool. If the value is true, then statement-false is discarded (if present), otherwise, statement-true is discarded.


2 Answers

A year after posting this question I now know why this is not a good idea. It's because the two are not actually equivalent.

if constexpr is just a facility that doesn't instantiate the discarded branch. That's it. This means that code like:

void draw() {
#if LINUX
    ncursesDrawWhatever();
#elif WINDOWS
    Win32Draw();
#endif
}

(which is perfectly fine right now) is not equivalent to:

void draw() {
    if constexpr (__linux)
        ncursesDrawWhatever();
    else if constexpr (__win)
        Win32Draw();
}

because on both platforms the two functions need to be available (and on the preprocessor version they do not). In this case the constexpr is completely redundant because it does nothing. Having to define both functions on both platforms just for one not being used is a bit of a pain, which is why the preprocessor was used in this way in the first place!

like image 93
Rakete1111 Avatar answered Oct 17 '22 20:10

Rakete1111


Probably because you haven't written one. These are fairly new things in the language. It takes time for an idea like that to filter down to actual code that's implemented and changes in how things are done.

As an example, I went through the Python asyncio package, and despite the creation of async and await keywords in the language specifically to support the use-cases of this package, it uses them in very few places and uses the @coroutine decorator most places still. This wasn't really too surprising.

So, post the feature request. Ask for some nice os testing constants that can be used with constexpr conditionals. Or maybe even commit to digging into the library to implement them yourself. The feature is less than 2 years old. So it shouldn't be a surprise this hasn't been done yet.

like image 41
Omnifarious Avatar answered Oct 17 '22 21:10

Omnifarious