预处理器检查 constexpr const char* 函数

Preprocessor check constexpr const char* function

我正在使用一个新版本的库,它以 static constexpr const char* 函数的形式给出了它的版本。我在测试时在新旧版本之间切换,我想包装我的代码,它只在预处理器检查中的 6.0 版中编译

下面我模拟了库如何显示版本号以及我尝试检测它是否以 '6':

开头
#include <iostream>

// This comes from a library
static constexpr const char* VersionNumber() { return "6.0"; }

// This would be my intended method of detecting the version number
static constexpr bool isVersionSix() { return VersionNumber()[0] == '6'; }

int main() {
    std::cout << "Code for any version\n";

#if isVersionSix()
    std::cout << "Additional code for version 6.0\n";
#endif

    return 0;
}

很遗憾,这是一个编译器错误:

foo.cpp:12:17: error: missing binary operator before token "("
 #if isVersionSix()

我该如何解决这个问题?在旁注中,我认为检查 '6' 而不是 "6.0" 对 SO 来说会更容易,如果这可以编译然后制作 constexpr 字符串比较函数应该不是问题

How can I get around this?

选项 1

您可以在运行时间测试版本并调用合适的函数或有代码块。

int main() {
    std::cout << "Code for any version\n";

    if ( isVersionSix() )
    {
       std::cout << "Additional code for version 6.0\n";
    }

    return 0;
}

选项 2

如果在 运行 时间分支不是选项,您可以使用一个函数模板,它是以前版本的 noop 并在 6.0 版本中做一些事情。

template <bool>
void doSomething()
{
   // Do nothing
}

// Specialization of the function template
template <> void doSomething<true>()
{
   std::cout << "Additional code for version 6.0\n";
}

int main() {
    std::cout << "Code for any version\n";

    doSomething<isVersionSix()>();

    return 0;
}

如果可以升级到GCC 7,可以使用if constexpr,如下:

#include <iostream>

// This comes from a library
static constexpr const char* VersionNumber() { return "6.0"; }

// This would be my intended method of detecting the version number
static constexpr bool isVersionSix() { return VersionNumber()[0] == '6'; }

int main() {
    std::cout << "Code for any version\n";

    if constexpr (isVersionSix()) {
        std::cout << "Additional code for version 6.0\n";
    }

    return 0;
}

(live example)

你可以看出,如果你没有它,它甚至不会编译版本 6 的东西,因为即使在 -O0 它甚至不会将 "Additional code for version 6.0\n" 放入编译的如果您更改版本号,则程序。

但是,无论如何,您可能希望改进您​​的版本检查功能。例如,如果库升级到版本 7,您的代码将不再有效;您可能想要更新以检查版本是否大于 6 而不是等于 6。但是,如果你这样做,请注意你不会 运行 进入版本 10 的问题。