【问题标题】:constexpr - function cannot be used in a constant expressionconstexpr - 函数不能用于常量表达式
【发布时间】:2016-07-29 14:25:31
【问题描述】:

我想在编译时为给定范围内的数学函数计算查找表,然后在运行时从表中检索值。我的代码如下:

#include <iostream>
#include <cmath>


template<int size>
class LookupTable {
public:
constexpr LookupTable(double xMin, double xMax) : array(), xMin(xMin), xMax(xMax), dx((xMax - xMin) / (size - 1)) {
    for(auto i = 0; i < size; ++i)
        array[i] = exp(xMin + i * dx);
}

constexpr double operator()(double x) const {
    return array[std::min(std::max(static_cast<int>((x - xMin) / dx), 0), size-1)];
}

private:
double array[size];
double xMin;
double xMax;
double dx;
};



int main() {
    const double x = 0.5;
    constexpr LookupTable<10000> table(0.0, 1.0);
    std::cout << "f(x) = " << table(x) << std::endl;  // evaluated at compile time ?
    std::cout << "f(x) = " << LookupTable<10000>(0.0, 1.0)(x) << std::endl;  // evaluated at run time ?
    return 0;
}

代码可以在 gcc 5.1 及更高版本上编译和运行,但不能在 Clang 3.8 上编译和运行。 Clang 的错误信息是:constexpr variable 'table' must be initialized by a constant expression and non-constexpr function 'exp' cannot be used in a constant expression.

当我删除 constexpr 时:

constexpr LookupTable<10000> table(0.0, 1.0);

然后代码也会在 Clang 上编译和运行。

我的问题是:

  • 错误信息“函数'exp'不能用于常量表达式”是什么意思?是否有解决方法?
  • 这是否意味着当我声明 LookupTable table(0.0, 1.0);如果没有 constexpr,那么表预计算会在运行时发生吗? 我正在使用在线编译工具,因此我目前无法选择对代码进行基准测试。
  • 我想概括代码并将数学函数模板化。它适用于仿函数,但可以使用 lambdas 吗?

谢谢

【问题讨论】:

    标签: c++ g++ c++14 constexpr cmath


    【解决方案1】:

    这似乎是 gcc 的不合格扩展,因为在 &lt;cmath&gt; 中声明了 exp() 而没有 constexpr

    17.6.5.6 constexpr 函数和构造函数 [constexpr.functions]

    1 本标准明确要求 某些标准库函数是 constexpr (7.1.5)。 安 实现不应声明任何标准库函数 作为 constexpr 的签名,但明确表示的除外 必需。 在提供任何非定义的任何标题中 constexpr 函数或构造函数的声明一个实现 应提供相应的定义。

    如果LookupTable 前面没有constexpr,它确实会在运行时初始化。一种解决方法是将其设为static 变量,以便您可以在启动时对其进行初始化。

    如果您想要constexpr 数学函数,您需要编写自己的,或者编写一个标准提案,将当前的&lt;cmath&gt; 库修改为constexpr

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-08
      • 1970-01-01
      • 2015-06-15
      • 2021-11-17
      • 1970-01-01
      相关资源
      最近更新 更多