Search code examples
c++classc-preprocessorc++17if-constexpr

Something like "if constexpr" but for class definition


if constexpr is a big step for getting rid of preprocessor in C++ programs. However it works only in functions - like in this example:

enum class OS
{
    Linux,
    MacOs,
    MsWindows,
    Unknown
};

#if defined(__APPLE__)
constexpr OS os = OS::MacOs;
#elif defined(__MINGW32__)
constexpr OS os = OS::MsWindows;
#elif defined(__linux__)
constexpr OS os = OS::Linux;
#else
constexpr OS os = OS::Unknown;
#endif

void printSystem()    
{
    if constexpr (os == OS::Linux)
    {
        std::cout << "Linux";
    }
    else if constexpr (os == OS::MacOs)
    {
        std::cout << "MacOS";
    }
    else if constexpr (os == OS::MsWindows)
    {
        std::cout << "MS Windows";
    }
    else
    {
        std::cout << "Unknown-OS";
    }
}

But dreams about getting rid of preprocessor are not quite satisfied - because the following examples do not compile:

1 Cannot use it in class definition to define some members of class differently:

class OsProperties
{
public:
    static void printName()
    {
        std::cout << osName;
    }
private:
    if constexpr (os == OS::Linux)
    {
        const char* const osName = "Linux";
    }
    else if constexpr (os == OS::MacOs)
    {
        const char* const osName = "MacOS";
    }
    else if constexpr (os == OS::MsWindows)
    {
        const char* const osName = "MS Windows";
    }
    else
    {
        const char* const osName = "Unknown";
    }
};

2 Nor it works for not class-scope (like global scope):

if constexpr (os == OS::Linux)
{
    const char* const osName = "Linux";
}
else if constexpr (os == OS::MacOs)
{
    const char* const osName = "MacOS";
}
else if constexpr (os == OS::MsWindows)
{
    const char* const osName = "MS Windows";
}
else
{
    const char* const osName = "Unknown";
}

I am (almost) sure this is per C++17 specification that if constexpr works only within function bodies - but my questions are:

Q1 How to achieve the similar effect like if-constexpr in functions - for class and global scope in C++1z/C++14? And I am not asking here for yet another explanation of template specialization... But something that has similar simplicity as if constexpr...

Q2 Are there any plan to extend C++ for the above mentioned scopes?


Solution

  • How to achieve the similar effect like if-constexpr in functions - for class and global scope in C++1z/C++14? And I am not asking here for yet another explanation of template specialization...

    You basically just said, "I want template specialization, but without all that pesky template specialization."

    if constexpr is the tool for making the behavior of functions change based on compile-time constructs. Template specialization is the tool that C++ provides for making definitions change based on compile-time constructs. It is the only tool C++ provides for this functionality.

    Now for your simplistic case of initializing a variable, you can always create and call a lambda. C++17 offers constexpr support for lambdas, and a lambda would be able to use if constexpr to decide what value to return.

    Are there any plan to extend C++ for the above mentioned scopes?

    No. Here are all of the proposals, and none of the ones from the past couple of years delve into this domain.

    And it's highly unlikely they ever will.