sep*_*p2k 39 c++ constexpr c++11
在C++ 11中std::sqrt
定义为constexpr
,即它可以合法地从其他constexpr
函数或编译时上下文中使用,如数组大小或模板参数吗?g ++似乎允许它(使用-std=c++0x
),但我不确定我是否可以将其视为权威,因为c ++ 0x/c ++ 11支持仍然不完整.我似乎无法在互联网上找到任何东西的事实让我不确定.
看起来这应该是人们可以轻易找到使用谷歌的东西,但我已经尝试过(现在40分钟......)并且找不到任何东西.我可以找到几个建议,将constexpr添加到标准库的各个部分(例如这个),但没有关于sqrt
或其他数学函数.
Nic*_*las 25
std::sqrt
constexpr
根据N3291第26.8节,没有定义为:C++ 11 FDIS(我怀疑他们之后将其添加到最终标准中).有人可能会编写这样的版本,但标准库版本却没有constexpr
.
Ara*_*raK 23
为了防止任何人对元整数平方根函数感兴趣,这里是我之前写的一个:
constexpr std::size_t isqrt_impl
(std::size_t sq, std::size_t dlt, std::size_t value){
return sq <= value ?
isqrt_impl(sq+dlt, dlt+2, value) : (dlt >> 1) - 1;
}
constexpr std::size_t isqrt(std::size_t value){
return isqrt_impl(1, 3, value);
}
Run Code Online (Sandbox Code Playgroud)
Ale*_*tof 16
这是一个快速有效的constexpr实现double
浮点数.float
如果需要,您也可以调整它:
#include <limits>
namespace Detail
{
double constexpr sqrtNewtonRaphson(double x, double curr, double prev)
{
return curr == prev
? curr
: sqrtNewtonRaphson(x, 0.5 * (curr + x / curr), curr);
}
}
/*
* Constexpr version of the square root
* Return value:
* - For a finite and non-negative value of "x", returns an approximation for the square root of "x"
* - Otherwise, returns NaN
*/
double constexpr sqrt(double x)
{
return x >= 0 && x < std::numeric_limits<double>::infinity()
? Detail::sqrtNewtonRaphson(x, x, 0)
: std::numeric_limits<double>::quiet_NaN();
}
Run Code Online (Sandbox Code Playgroud)
Lin*_*umz 13
下面是一个使用二进制搜索的constexpr平方根实现.对于gcc和clang,它可以正常工作到2 ^ 64,其他更简单的版本通常会因数字> 2 ^ 32而失败,因为编译器将递归深度限制为例如200.
// C++11 compile time square root using binary search
#define MID ((lo + hi + 1) / 2)
constexpr uint64_t sqrt_helper(uint64_t x, uint64_t lo, uint64_t hi)
{
return lo == hi ? lo : ((x / MID < MID)
? sqrt_helper(x, lo, MID - 1) : sqrt_helper(x, MID, hi));
}
constexpr uint64_t ct_sqrt(uint64_t x)
{
return sqrt_helper(x, 0, x / 2 + 1);
}
Run Code Online (Sandbox Code Playgroud)
下面是一个更好的版本(对于整数常量)需要C++ 14,它类似于Baptiste Wicht 博客文章中提供的版本.允许C++ 14 constexpr函数使用局部变量和if语句.
// C++14 compile time square root using binary search
template <typename T>
constexpr T sqrt_helper(T x, T lo, T hi)
{
if (lo == hi)
return lo;
const T mid = (lo + hi + 1) / 2;
if (x / mid < mid)
return sqrt_helper<T>(x, lo, mid - 1);
else
return sqrt_helper(x, mid, hi);
}
template <typename T>
constexpr T ct_sqrt(T x)
{
return sqrt_helper<T>(x, 0, x / 2 + 1);
}
Run Code Online (Sandbox Code Playgroud)
现在有一个提案P1383R0 More constexpr for <cmath>
and <complex>
(Edward J. Rosten, Oliver J. Rosten)不幸的是没有进入 C++20 并且从最新的评论来看也可能不在 C++23 中。C++26?
如果我们查看最接近C++ 11 N3337的标准草案,我们可以看到sqrt
没有标记为constexpr,来自26.8
c.math部分:
这些标头的内容分别与标准C库标头相同,但有以下更改:
没有任何的变化包括增加constexpr来sqrt
.
我们可以从问题中看出,gcc将非常量表达式函数的内置函数视为常量表达式,将gcc
许多数学函数标记为constexpr作为扩展.这个扩展是一个不合格的扩展,正如我在gcc
实现时对链接问题的回答中所注意到的,它看起来像是一个符合标准的扩展,但是这个改变了,gcc
并且可能会修复这个扩展以使其符合要求.