constexpr递归函数使用if constexpr与否

Pap*_*ter 4 c++ constexpr c++17

使用gcc(HEAD 7.0.0 201612)我很惊讶地发现这有效:

constexpr long value(const char *definition)
{
    if (definition && *definition)
    {
        return *definition + value(definition + 1);
    }

    return *definition;
}

int main()
{
    long l{};
    std::cin >> l;

    switch (l)
    {
        case value("AAAA"): f1(); break;
        case value("BBBB"): f2(); break;
        default: error();         break;
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

的文字串"AAAA""BBBB"被当作编译时值和调用value函数产生的值260264直接在使用switch上下文; 我应该承认我期待编译器抱怨" 字符串不是常量表达式 ".所以我转到下一步并尝试添加一个if constexpr算法:

constexpr long value(const char *definition)
{
    if constexpr (definition && *definition)
    {
        return *definition + value(definition + 1);
    }

    return *definition;
}
Run Code Online (Sandbox Code Playgroud)

但是通过添加if constexpr代码不再编译:

In function 'constexpr long int value(const char*)':
 error: 'definition' is not a constant expression
     if constexpr (definition && *definition)
                                            ^
Run Code Online (Sandbox Code Playgroud)

因此,似乎definition指针本身在if constexpr上下文中的编译时是不可评估的,但是使用传统if的整个函数在编译时是可评估的.

为什么会这样?

Nic*_*las 6

这是因为你不能这样做的原因:

constexpr auto func(const int foo)
{
  return std::array<int, foo>{};
}
Run Code Online (Sandbox Code Playgroud)

foo可能会也可能不会是一个恒定的表达,取决于你如何调用func.但是你放入模板参数的必须是一个常量表达式.因此,此代码无法编译.

你的value功能也一样.你输入的内容if constexpr 必须是一个常量表达式,就像模板参数一样.所以你不能在那里放一些可能是也可能不是常量表达式的东西,比如constexpr函数的参数.