Constexpr递归函数是否使用If ConstexPR

constexpr recursive function using if constexpr or not

本文关键字:If ConstexPR 递归函数 是否 Constexpr      更新时间:2023-10-16

使用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函数的调用会产生直接在switch上下文中使用的260264的值;我应该承认,我期望编译器抱怨" 字符串不是恒定表达式"。因此,我搬到了下一步,并尝试将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,可以在编译时间评估整个函数。

为什么会发生?

发生的原因是不能这样做的原因相同:

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

foo May 或可能不是是恒定表达式,具体取决于您调用func的方式。但是,您将其放入模板参数必须是一个恒定的表达式。因此,此代码无法编译。

您的value功能也是如此。您将其放入if constexpr 必须是一个恒定的表达式,就像模板参数一样。因此,您不能将某些内容放在那里可能会或可能不是恒定表达式的东西,例如constexpr函数的参数。