确定 `constexpr` 的执行 - 在编译期间还是在运行时?
Determine `constexpr` execution - during compilation or at runtime?
有没有办法在编译阶段和运行时实现 constexpr
函数的不同行为?
考虑以下示例(使用 D: static if
中的理论特征):
constexpr int pow( int base , int exp ) noexcept
{
static if( std::evaluated_during_translation() ) {
auto result = 1;
for( int i = 0 ; i < exp ; i++ )
result *= base;
return result;
} else { // std::evaluated_during_runtime()
return std::pow( base , exp );
}
}
如果不是,有没有办法限制 constexpr
仅在编译时?
不,没有这样的方法。
对不起。
N3583 is a paper 提出更改以实现您的要求。
在 C++20 之前,这是不可能的。 C++20 然后添加了 std::is_constant_evaluated
这正是这个用例:
constexpr int pow(int base, int exp) noexcept
{
if (std::is_constant_evaluated())
{
auto result = 1;
for (int i = 0; i < exp; i++)
result *= base;
return result;
}
else
{
return std::pow(base, exp);
}
}
请注意,if
语句本身是 而不是 constexpr
。如果是,整个 else 分支将从函数中删除,它总是 运行 if 分支,无论是在编译时还是 运行 时。使用普通的 if 语句,您基本上可以获得两个函数。一个在编译时 运行s:
constexpr int pow(int base, int exp) noexcept
{
auto result = 1;
for (int i = 0; i < exp; i++)
result *= base;
return result;
}
还有一个在 运行 时间编译了 运行 秒:
constexpr int pow(int base, int exp) noexcept
{
return std::pow(base, exp);
}
编译器可以安全地删除 if 分支,因为它可以证明它在 运行 时间不可访问。很整洁。
有没有办法在编译阶段和运行时实现 constexpr
函数的不同行为?
考虑以下示例(使用 D: static if
中的理论特征):
constexpr int pow( int base , int exp ) noexcept
{
static if( std::evaluated_during_translation() ) {
auto result = 1;
for( int i = 0 ; i < exp ; i++ )
result *= base;
return result;
} else { // std::evaluated_during_runtime()
return std::pow( base , exp );
}
}
如果不是,有没有办法限制 constexpr
仅在编译时?
不,没有这样的方法。
对不起。
N3583 is a paper 提出更改以实现您的要求。
在 C++20 之前,这是不可能的。 C++20 然后添加了 std::is_constant_evaluated
这正是这个用例:
constexpr int pow(int base, int exp) noexcept
{
if (std::is_constant_evaluated())
{
auto result = 1;
for (int i = 0; i < exp; i++)
result *= base;
return result;
}
else
{
return std::pow(base, exp);
}
}
请注意,if
语句本身是 而不是 constexpr
。如果是,整个 else 分支将从函数中删除,它总是 运行 if 分支,无论是在编译时还是 运行 时。使用普通的 if 语句,您基本上可以获得两个函数。一个在编译时 运行s:
constexpr int pow(int base, int exp) noexcept
{
auto result = 1;
for (int i = 0; i < exp; i++)
result *= base;
return result;
}
还有一个在 运行 时间编译了 运行 秒:
constexpr int pow(int base, int exp) noexcept
{
return std::pow(base, exp);
}
编译器可以安全地删除 if 分支,因为它可以证明它在 运行 时间不可访问。很整洁。