constexpr
函数中不允许使用static
变量。这是有道理的,因为static
会向本应是纯函数的函数引入状态。
然而,我不明白为什么我们不能在constexpr
函数中有一个static constexpr
变量。它保证始终具有相同的值,因此该函数将保持纯净。
为什么我会关心呢?因为在运行时static
会产生影响。考虑以下代码:
#include <array>
constexpr int at(const std::array<int, 100>& v, int index)
{
return v[index];
}
int foo1(int i) {
static constexpr std::array<int, 100> v = {
5, 7, 0, 0, 5 // The rest are zero
};
return at(v, i);
}
constexpr int foo2(int i) {
constexpr std::array<int, 100> v = {
5, 7, 0, 0, 5 // The rest are zero
};
return at(v, i);
}
int foo2_caller(int i) {
return foo2(i);
}
实时链接: https://gcc.godbolt.org/z/umdXgv
foo1
具有3个汇编指令,因为它将缓冲区存储在静态存储中。而foo2
具有15个汇编指令,因为每次调用都需要分配和初始化缓冲区,编译器无法对其进行优化。
请注意,foo1
只是为了显示foo2
中的缺陷。我想编写一个既能在编译时又能在运行时使用的函数。这就是foo2
的想法。但是我们看到它不能像仅限于运行时的foo1
那样高效,这很令人不安。
我找到的唯一有意义的相关讨论在这里,但它并没有特别讨论static constexpr
。
这些问题是:
- 我的推理正确吗?还是我错过了
static constexpr
变量可能引起的问题? - 有没有修复这个问题的提案?
foo1
呢? - NathanOliverfoo1
仍然不允许在constexpr
上下文中使用。 - Mikhailconstexpr
函数调用之间持久存在的“状态”,而这些函数本来应该是无状态的。这并非不可能实现,只是当前规则会使其变得复杂,并需要进行一些大的更改才能允许它。 - Human-Compiler