在C ++ 11中,sqrt被定义为constexpr?

时间:2011-12-24 02:18:06

标签: c++ c++11 constexpr

在C ++ 11中,std::sqrt定义为constexpr,即它是否可以合法地从其他constexpr函数或编译时上下文(如数组大小或模板参数)中使用? g ++似乎允许它(使用-std=c++0x),但我不确定我是否可以将其视为权威,因为c ++ 0x / c ++ 11支持仍然不完整。事实上,我似乎无法在互联网上找到任何东西,这让我不确定。

看起来这应该是人们可以轻易找到使用谷歌的东西,但我已经尝试过(现在40分钟......)并且找不到任何东西。我可以找到几个建议,将constexpr添加到标准库的各个部分(例如this one),但没有关于sqrt或其他数学函数的内容。

6 个答案:

答案 0 :(得分:24)

根据N3291第26.8节,

std::sqrt未被定义为constexpr:C ++ 11 FDIS(我怀疑他们之后将其添加到最终标准中)。有人可能会编写这样的版本,但标准库版本不是constexpr

答案 1 :(得分: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);
}

答案 2 :(得分:14)

这是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();
}

答案 3 :(得分:13)

下面是一个使用二进制搜索的constexpr平方根实现。它使用gcc和clang可以正常工作到2 ^ 64,其他更简单的版本通常会因数字而失败&gt;因为编译器将递归深度限制为例如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的blog post中提供的版本。允许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);
}

答案 4 :(得分:7)

如果我们查看最接近C ++ 11的标准草案N3337,我们可以看到sqrt未标记为 constexpr ,来自26.8 < EM> c.math :

  

这些标头的内容与标准C库相同   标题和分别具有以下内容   变化:

所有更改都不包括将 constexpr 添加到sqrt

我们可以从问题Is gcc considering builtins of non-constant expression functions to be constant expressions看出,gcc将许多数学函数标记为 constexpr 作为扩展名。这个扩展名为non-conforming extension,正如我在gcc实施此问题时对链接问题的回答中所述,它看起来像是一个符合标准的扩展名,但这已经改变,gcc可能会修复这个扩展要符合要求。

答案 5 :(得分:3)

现在有一个提案P1383R0 More constexpr for <cmath> and <complex> (Edward J. Rosten, Oliver J. Rosten),不幸的是尚未纳入C ++ 20,从最新评论来看,也可能不在C ++ 23中。 C ++ 26?