constexpr递归函数使用if constexpr与否

时间:2016-12-21 15:25:31

标签: 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;
}

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

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

    return *definition;
}

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

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

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

为什么会这样?

1 个答案:

答案 0 :(得分:6)

出现这种情况的原因与您无法做到的原因相同:

constexpr auto func(const int foo)
{
  return std::array<int, foo>{};
}

foo可能或者可能不是是一个常量表达式,具体取决于您调用func的方式。但是你放入模板参数的内容必须是一个常量表达式。因此,此代码无法编译。

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