常量整数和常量求值
Constant integers and constant evaluation
考虑以下程序:
#include <iostream>
#include <type_traits>
constexpr int f() {
if (std::is_constant_evaluated())
return -1;
else return 1;
}
int main() {
int const i = f();
std::cout << i;
}
它prints -1
when run(魔杖盒)。
但是,如果我在编译时计算函数 throw
::
#include <iostream>
#include <type_traits>
constexpr int f() {
if (std::is_constant_evaluated())
throw -1; // <----------------------- Changed line
else return 1;
}
int main() {
int const i = f();
std::cout << i;
}
它compiles fine and outputs 1(魔杖盒)。为什么我没有得到编译失败?
不断评价是不是很有趣?
语言中有几个地方我们尝试进行持续评估,如果失败,我们回退到不做-不断的评估。静态初始化是一个这样的地方,初始化常量整数是另一个地方。
发生了什么:
int const i = f();
是这个可以不断求值,但不一定非得如此。因为(非constexpr
)常量整数仍然可以用作常量表达式,如果满足所有其他条件,我们必须尝试。例如:
const int n = 42; // const, not constexpr
std::array<int, n> arr; // n is a constant expression, this is ok
所以我们尝试这样做 - 我们将 f()
称为常量表达式。在这种情况下,std::is_constant_evaluated()
是 true
,因此我们使用 throw
命中分支并最终失败。不能 throw
在持续评估期间,因此我们的持续评估失败。
但随后我们回退,再次尝试 - 这次将 f()
作为非常量表达式调用(即 std::is_constant_evaluated()
是 false
)。这条路径成功,给我们 1
,因此 i
被初始化为值 1
。但值得注意的是,i
此时 不是 常量表达式。随后的 static_assert(i == 1)
将是错误格式的,因为 i
的初始值设定项 不是 常量表达式!即使非常量初始化路径恰好(否则)完全满足常量表达式的要求。
请注意,如果我们尝试:
constexpr int i = f();
这会失败,因为我们无法回退到非常量初始化。
考虑以下程序:
#include <iostream>
#include <type_traits>
constexpr int f() {
if (std::is_constant_evaluated())
return -1;
else return 1;
}
int main() {
int const i = f();
std::cout << i;
}
它prints -1
when run(魔杖盒)。
但是,如果我在编译时计算函数 throw
::
#include <iostream>
#include <type_traits>
constexpr int f() {
if (std::is_constant_evaluated())
throw -1; // <----------------------- Changed line
else return 1;
}
int main() {
int const i = f();
std::cout << i;
}
它compiles fine and outputs 1(魔杖盒)。为什么我没有得到编译失败?
不断评价是不是很有趣?
语言中有几个地方我们尝试进行持续评估,如果失败,我们回退到不做-不断的评估。静态初始化是一个这样的地方,初始化常量整数是另一个地方。
发生了什么:
int const i = f();
是这个可以不断求值,但不一定非得如此。因为(非constexpr
)常量整数仍然可以用作常量表达式,如果满足所有其他条件,我们必须尝试。例如:
const int n = 42; // const, not constexpr
std::array<int, n> arr; // n is a constant expression, this is ok
所以我们尝试这样做 - 我们将 f()
称为常量表达式。在这种情况下,std::is_constant_evaluated()
是 true
,因此我们使用 throw
命中分支并最终失败。不能 throw
在持续评估期间,因此我们的持续评估失败。
但随后我们回退,再次尝试 - 这次将 f()
作为非常量表达式调用(即 std::is_constant_evaluated()
是 false
)。这条路径成功,给我们 1
,因此 i
被初始化为值 1
。但值得注意的是,i
此时 不是 常量表达式。随后的 static_assert(i == 1)
将是错误格式的,因为 i
的初始值设定项 不是 常量表达式!即使非常量初始化路径恰好(否则)完全满足常量表达式的要求。
请注意,如果我们尝试:
constexpr int i = f();
这会失败,因为我们无法回退到非常量初始化。