Simplify Nested #ifdef Chains in C++23

Simplify Nested #ifdef Chains in C++23

Complex preprocessor conditionals often introduce deeply nested #ifdef blocks, making the code harder to read and maintain. These patterns are common when detecting compiler types, platform features, or optional modules.

Consider the following classic approach for compiler detection:

#include <iostream>

#ifdef __clang__
    #define COMPILER "Clang"
#else
    #ifdef __GNUC__
        #define COMPILER "GCC"
    #else
        #ifdef _MSC_VER
            #define COMPILER "MSVC"
        #else
            #define COMPILER "Unknown"
        #endif
    #endif
#endif

int main() {
    std::cout << COMPILER << std::endl;

    return 0;
}

While functional, the nested structure complicates maintenance. Adding new compiler checks or modifying existing ones often requires careful tracking of multiple nested branches, which can lead to subtle errors.

Since C++23, we can use #elifdef and #elifndef preprocessor directives, streamlining nested chains. These directives allow multiple conditions to be evaluated sequentially without deep nesting, improving readability and reducing boilerplate.

#include <iostream>

#ifdef __clang__
    #define COMPILER "Clang"
#elifdef __GNUC__
    #define COMPILER "GCC"
#elifdef _MSC_VER
    #define COMPILER "MSVC"
#else
    #define COMPILER "Unknown"
#endif

int main() {
    std::cout << COMPILER << std::endl;

    return 0;
}

Leave a Comment

Cancel reply

Your email address will not be published.