Ниже приведена реализация квадратного корня constexpr, которая использует бинарный поиск. Он работает корректно до 2 ^ 64 с gcc и clang, другие более простые версии часто терпят неудачу для чисел> 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, она аналогична той, что представлена в блоге Баптиста Вихта . 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);
}