constexpr - 函数不能用在常量表达式中
constexpr - function cannot be used in a constant expression
我想在编译时为给定范围内的数学函数计算查找 table,然后在 运行 时从 table 检索值。我的代码如下:
#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 及更高版本上编译和 运行s,但在 Clang 3.8 上不编译。
Clang 的错误消息是:constexpr 变量 'table' 必须由常量表达式初始化并且非 constexpr 函数 'exp' 不能在常量表达式中使用。
当我删除 constexpr 时:
constexpr LookupTable<10000> table(0.0, 1.0);
然后代码在 Clang 上编译和 运行s。
我的问题是:
- 错误消息 "function 'exp' cannot be used in a constant expression" 的含义是什么?有解决方法吗?
- 这是否意味着当我声明 LookupTable<10000> table(0.0, 1.0);如果没有 constexpr,那么 table 预计算发生在 运行 时间?
我正在使用在线编译工具,所以我现在无法选择对代码进行基准测试。
- 我想概括代码并模板化数学函数。它适用于函子但可以使用 lambdas 吗?
谢谢
这似乎是 gcc 的不符合要求的扩展,因为 exp()
在 <cmath>
中声明时没有 constexpr
:
17.6.5.6 constexpr functions and constructors [constexpr.functions]
1 This standard explicitly requires that
certain standard library functions are constexpr (7.1.5). An
implementation shall not declare any standard library function
signature as constexpr except for those where it is explicitly
required. Within any header that provides any non-defining
declarations of constexpr functions or constructors an implementation
shall provide corresponding definitions.
如果你的 LookupTable
前面没有 constexpr
,它确实会在运行时初始化。一种解决方法是将其设为 static
变量,以便您可以在启动时对其进行初始化。
如果你想要 constexpr
数学函数,你需要自己写,或者写一个标准提案,将当前的 <cmath>
库修改为 constexpr
。
我想在编译时为给定范围内的数学函数计算查找 table,然后在 运行 时从 table 检索值。我的代码如下:
#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 及更高版本上编译和 运行s,但在 Clang 3.8 上不编译。 Clang 的错误消息是:constexpr 变量 'table' 必须由常量表达式初始化并且非 constexpr 函数 'exp' 不能在常量表达式中使用。
当我删除 constexpr 时:
constexpr LookupTable<10000> table(0.0, 1.0);
然后代码在 Clang 上编译和 运行s。
我的问题是:
- 错误消息 "function 'exp' cannot be used in a constant expression" 的含义是什么?有解决方法吗?
- 这是否意味着当我声明 LookupTable<10000> table(0.0, 1.0);如果没有 constexpr,那么 table 预计算发生在 运行 时间? 我正在使用在线编译工具,所以我现在无法选择对代码进行基准测试。
- 我想概括代码并模板化数学函数。它适用于函子但可以使用 lambdas 吗?
谢谢
这似乎是 gcc 的不符合要求的扩展,因为 exp()
在 <cmath>
中声明时没有 constexpr
:
17.6.5.6 constexpr functions and constructors [constexpr.functions]
1 This standard explicitly requires that certain standard library functions are constexpr (7.1.5). An implementation shall not declare any standard library function signature as constexpr except for those where it is explicitly required. Within any header that provides any non-defining declarations of constexpr functions or constructors an implementation shall provide corresponding definitions.
如果你的 LookupTable
前面没有 constexpr
,它确实会在运行时初始化。一种解决方法是将其设为 static
变量,以便您可以在启动时对其进行初始化。
如果你想要 constexpr
数学函数,你需要自己写,或者写一个标准提案,将当前的 <cmath>
库修改为 constexpr
。