以下は、二分探索を使用するconstexpr平方根の実装です。gccとclangでは2^64まで正しく動作しますが、コンパイラが再帰の深さをたとえば200に制限しているため、他の単純なバージョンは2^32を超える数値で失敗することがよくあります。
// 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を必要とするより良いバージョン(整数定数用)であり、BaptisteWichtのブログ投稿に示されているものと似ています。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);
}