在c++ 11中,sqrt定义为constexpr
In C++11 is sqrt defined as constexpr?
在c++ 11中std::sqrt
被定义为constexpr
,即它可以合法地从其他constexpr
函数或在编译时上下文中使用,如数组大小或模板参数?g++似乎允许它(使用-std=c++0x
),但我不确定我可以把它作为权威,因为c++0x/c++11的支持仍然不完整。我在网上似乎找不到任何东西,这一事实使我拿不准。
似乎这应该是一个可以很容易地找到用谷歌,但我已经尝试了(40分钟了…),没有找到任何东西。我可以找到几个将constexpr添加到标准库的各个部分的建议(例如这个),但没有关于sqrt
或其他数学函数的建议。
std::sqrt
没有定义为constexpr
,根据N3291: c++ 11 FDIS的第26.8节(我怀疑他们在那之后将其添加到最终标准中)。可以编写这样一个版本,但是标准库版本不是constexpr
。
这是double
浮点数的快速有效的constexpr实现。如果需要,您也可以将其调整为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();
}
如果有人对元整数平方根函数感兴趣,这里是我一年前写的一个:
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);
}
下面是一个使用二进制搜索的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);
}
下面是一个更好的版本(用于整型常量),它需要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);
}
现在有一个提案P1383R0 <cmath>
和<complex>
的更多constexpr (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
很可能会修复这个扩展是符合要求的。
- 通过 lambda 定义的 constexpr 递归函数
- 将预处理器配置定义迁移到 constexpr,而不会造成内存膨胀
- 如何将用户定义的文字放在C++相同类型的 constexpr 类中?
- 我可以定义一个 constexpr 匿名/未命名变量吗?
- 使用模板参数还包括 constexpr 成员函数enable_if单独定义和声明模板成员函数
- 在模板定义中调用非静态constexpr成员函数
- 编译器如何知道C++constexpr计算不会触发未定义的行为
- 有没有办法声明一个公共静态常量,该常量将使用 constexpr 在源文件中定义(有什么区别)?
- constexpr 用户定义的文字:允许吗?
- 为什么 #pragma 一次不防范多个非 constexpr 定义?
- constexpr 和未定义的行为
- 现在允许重新定义 constexpr 静态数据成员吗?(但不是内联常量)?
- 文件中定义的 Constexpr 构造函数.cpp会导致链接错误
- 定义 constexpr 静态数据成员
- 通过呼叫constexpr函数来定义静态constexpr成员
- constexpr:constexpr成员的定义和声明
- 在定义(.cpp文件)中初始化静态浮点 constexpr 成员是可能的
- C++11 - 无法使用 constexpr 函数定义 constexpr 文字?
- VC++编译器升级2010->2015重新定义; 'constexpr'说明符不匹配
- Clang抱怨在未求值的上下文中没有定义constexpr函数