替换模板元编程中的三元运算符 [英] Replacement for ternary operator in template metaprogramming

查看:28
本文介绍了替换模板元编程中的三元运算符的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在用 C++ 实现一个二项式系数(n 选择 k)函数.除了使用正常"函数(在运行时计算)之外,这也可以使用模板元编程(当参数在编译时已知)来完成:

I am implementing a binomial coefficient (n choose k) function in C++. Besides using a "normal" function (which is evaluated at runtime) this also can be accomplished using template metaprogramming (when the arguments are known at compile time):

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;
};

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

The drawback of this implementation is, that it does not make use of the theorem n choose k = n choose n-k in the cases where k > n/2. So unnecessary arithmetic overflow may occur, e.g. 49 choose 43 does overflow, whereas 49 choose 6 does not.

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

I have tried the following to improve this:

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;
};

不幸的是,我收到致命错误:模板实例化深度超过最大值 900.

这似乎是因为在递归模板实例化过程中没有评估三元运算符.

This seems to be caused by the fact, that the ternary operator is not evaluated during the process of recursive template instantiation.

使用 的可能替代方法是什么?: ?

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

I am interested in pre-C++11 solutions and newer solutions alike (maybe std::enable_if helps, but I do not know well about it).

推荐答案

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

After a night of sleep, I think I got the point with the std::conditional.

正如@Yakk 所提议的,我也自己实现了conditional.

As @Yakk has proposed, I also have implemented the conditional myself.

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

This implementation works with all C++ standards:

#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 ?).

Suggestions on how to make the code more concise or elegant (is it really necessary to use the second static member _value ?) are warmly welcome.

这篇关于替换模板元编程中的三元运算符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆