模板元编程中三元运算符的替换

2024-02-27

我正在 C++ 中实现二项式系数(n 选择 k)函数。 除了使用“正常”函数(在运行时评估)之外,还可以使用模板元编程来完成(当参数在编译时已知时):

template <unsigned int n, unsigned int k>
struct Binomialkoeffizient {
    static const unsigned int value = Binomialkoeffizient<n, k-1>::value * (n-k+1) / k;
};

template <unsigned int n>
struct Binomialkoeffizient<n, 0> {
    static const unsigned int value = 1;
};

这种实现的缺点是,它没有利用定理 n 选择 k = n 在 k > n/2 的情况下选择 n-k。因此可能会发生不必要的算术溢出,例如49 选择 43 会溢出,而 49 选择 6 不会溢出。

我尝试了以下方法来改善这一点:

template <unsigned int n, unsigned int k>
struct Binomialkoeffizient {
    static const unsigned int value = (2*k > n) ? Binomialkoeffizient<n, n-k>::value : Binomialkoeffizient<n, k-1>::value * (n-k+1) / k;
};

template <unsigned int n>
struct Binomialkoeffizient<n, 0> {
    static const unsigned int value = 1;
};

不幸的是,我得到fatal error: template instantiation depth exceeds maximum of 900.

这似乎是由于在递归模板实例化过程中没有计算三元运算符造成的。

有哪些可能的替代方法?: ?

我对 C++11 之前的解决方案和较新的解决方案感兴趣(也许std::enable_if有帮助,但我对此不太了解)。


经过一夜的睡眠,我想我明白了std::conditional.

Edit:正如@Yakk 所提议的,我也实现了conditional myself.

此实现适用于所有 C++ 标准:

#if __cplusplus >= 201103L
    // in C++11 and above we can use std::conditional which is defined in <type_traits>
    #include <type_traits>
    namespace my {
        using std::conditional;
    }
#else
    // in older C++ we have to use our own implementation of conditional
    namespace my {
        template <bool b, typename T, typename F>
        struct conditional {
            typedef T type;
        };

        template <typename T, typename F>
        struct conditional<false, T, F> {
            typedef F type;
        };
    }
#endif

template <unsigned int n, unsigned int k>
struct Binomialkoeffizient {
    static const unsigned int value = my::conditional< (2*k > n), Binomialkoeffizient<n, n-k>, Binomialkoeffizient<n, k> >::type::_value;
    static const unsigned int _value = Binomialkoeffizient<n, k-1>::_value * (n-k+1) / k;
};

template <unsigned int n>
struct Binomialkoeffizient<n, 0> {
    static const unsigned int value = 1;
    static const unsigned int _value = 1;
};

关于如何让代码更加简洁或者优雅的建议(真的有必要使用第二个静态成员吗_value?)受到热烈欢迎。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

模板元编程中三元运算符的替换 的相关文章

随机推荐