我已经定义了一个constexpr函数,如下所示:

constexpr int foo(int i)
{
    return i*2;
}

这就是主要功能:
int main()
{
    int i = 2;
    cout << foo(i) << endl;
    int arr[foo(i)];
    for (int j = 0; j < foo(i); j++)
        arr[j] = j;
    for (int j = 0; j < foo(i); j++)
        cout << arr[j] << " ";
    cout << endl;
    return 0;
}

该程序在OS X 10.8下使用命令clang++进行编译。令我惊讶的是,编译器未产生有关foo(i)不是常量表达式的任何错误消息,并且编译后的程序实际上运行良好。为什么?

最佳答案

在C++中constexpr函数的定义是这样的:保证函数在被调用时能够生成一个常量表达式,从而使得在评估中仅使用常量表达式。但是,没有指定评估结果是在编译时还是在运行时(如果结果未在constexpr中使用)(请参见this answer)。当将非常数表达式传递给constexpr时,您可能不会获得常数表达式。

但是,您上面的代码不应编译,因为i不是一个常量表达式,foo()显然使用该表达式来生成结果,然后将其用作数组维。似乎clang实现了C样式的可变长度数组,因为它为我产生了以下警告:

warning: variable length arrays are a C99 feature [-Wvla-extension]

判断某物是否确实是一个常数表达式的更好测试是使用它来初始化constexpr的值,例如:
constexpr int j = foo(i);

07-28 02:44
查看更多