在C++编译时没有内置的计算能力的方法吗?

Mic*_*ael 12 c++ templates compile-time-constant

我有以下非常简单的模板.据我所知,^不是指数运算符.现在我正在寻找一种计算这种能力的方法.互联网上有许多递归模板的例子.这不是太难.

但我想知道:在C++中实际上没有"内置"方法来在编译时计算它吗?

template <int DIM>
class BinIdx : Idx
{
        static const int SIZE = 3 ^ DIM; // whoops, this is NOT an exponential operator!
}
Run Code Online (Sandbox Code Playgroud)

rig*_*old 10

如上所述,<<如果指数是2的幂,则可以使用.

否则,如果指数是非负整数,则可以编写类似于此的constexpr函数.

template<typename T, typename U>
auto constexpr pow(T base, U exponent) {
    static_assert(std::is_integral<U>(), "exponent must be integral");
    return exponent == 0 ? 1 : base * pow(base, exponent - 1);
}
Run Code Online (Sandbox Code Playgroud)

不过,对于大型指数和负指数,这显然会受到打击.

我并不完全清楚编译器在常量表达式中如何优化函数调用.这是针对指数为2的幂的情况的手动优化.这也将减少完成的递归量.

template<typename T>
bool constexpr is_power_of_two(T x) {
    return (x != 0) && ((x & (x - 1)) == 0);
}

template<typename T, typename U>
auto constexpr pow(T base, U exponent) {
    static_assert(std::is_integral<U>(), "exponent must be integral");
    if (is_power_of_two(exponent)) {
        return base << exponent;
    }
    return exponent == 0 ? 1 : base * pow(base, exponent - 1);
}
Run Code Online (Sandbox Code Playgroud)

还可以使用更有效的算法.但是,我不擅长计算机科学,所以我不知道如何实现它们.

  • 如果你想进行优化,更好的优化是Squaring的Exponentiation:http://en.wikipedia.org/wiki/Exponentiation_by_squaring (4认同)
  • 我认为你的函数名称应该改变 - 因为`std :: pow`> o < (2认同)
  • 您的最后一点很重要:如果您不小心,很容易使编译器在编译时计算时爆炸.这是一个很好的理由****不能**在标准库中提供类似的东西 (2认同)
  • @ikh:你为什么这么说?`std`命名空间的重点是允许您为自己的函数提供合理的名称,而不存在与库名冲突的危险. (2认同)

Ant*_*vin 8

作为elyse答案的补充,这里的递归深度为log(n):

template<typename T>
constexpr T sqr(T a) {
    return a * a;
}

template<typename T>
constexpr T power(T a, std::size_t n) {
    return n == 0 ? 1 : sqr(power(a, n / 2)) * (n % 2 == 0 ?  1 : a);
}
Run Code Online (Sandbox Code Playgroud)


Flo*_*dis 5

不,没有通用的内置方法来计算值的幂。有pow标准库中的函数,您可以<<在特殊情况下使用移位运算符2^x

这适用于您的情况 (*):

static const int SIZE = (1 << DIM);
Run Code Online (Sandbox Code Playgroud)

* =在我写下答案后,您将问题从 更新2^x3^x

对于另一个特殊情况 x^y,其中 x 和 y 是静态的,您可以编写一个长乘法:

const result int = x*x*x*x*x;
Run Code Online (Sandbox Code Playgroud)


ikh*_*ikh 5

您可以使用模板元编程.让我展示一下代码.

template <int A, int B>
struct get_power
{
    static const int value = A * get_power<A, B - 1>::value;
};
template <int A>
struct get_power<A, 0>
{
    static const int value = 1;
};
Run Code Online (Sandbox Code Playgroud)

用法:

std::cout << get_power<3, 3>::value << std::endl;
Run Code Online (Sandbox Code Playgroud)

(实例)

  • OP 明确要求内置更直接的模板元编程替代方案。所以这不是答案。 (2认同)