具有非完全整数类型的结构和枚举

时间:2015-12-03 13:26:08

标签: c++ templates c++11 enums

现在我知道以下是如何工作的:

template<std::uint8_t num>
struct factorial 
{
    static_assert(num <= 20, "Integer overflow!!");
    enum { value = num * factorial<num - 1>::value };
};

template <>
struct factorial<0> 
{
    enum { value = 1 };
};

它在编译时使用递归计算数字的阶乘!

您可以像这样调用此函数:std::cout << factorial<20>::value;

很漂亮,但enum只能保存整数类型(最多std::uintmax_t)。这意味着我们无法计算大于20的数字的阶乘。

现在我写了一个很好的小bigint类,它删除了边界。

请考虑以下事项:

template<std::uintmax_t num>
struct factorial
{
    static bigint value()
    {
        bigint result("1");

        for (bigint i("2"); i <= num; ++i)
            result *= i;

        return result;
    }
};

这需要我这样称呼它:std::cout << factorial<99>::value();。显然......因为它是一个功能。

我的问题是:有没有办法修改代码/函数,所以它会被调用,就像第一个例子,但仍然使用bigint类,我不能坚持enum

1 个答案:

答案 0 :(得分:5)

首先,使用c ++ 14,您可以将value()变为constexpr

template<std::uintmax_t num>
struct factorial
{
    constexpr bigint value()
    {
        bigint result(1);
        for (bigint i(2); i <= num; ++i)
            result *= i;
        return result;
    }
};

int main()
{
    static_assert(factorial<3>().value() == 6, "");
}

现在,如果您想通过旧语法访问它,可以使用

轻松完成
template<std::uintmax_t num>
struct factorial
{
    constexpr static bigint calc_value()
    {
        bigint result(1);
        for (bigint i(2); i <= num; ++i)
            result *= i;
        return result;
    }

    constexpr static bigint value = calc_value();
};

...
static_assert(factorial<3>::value == 6, "");

Livebigintunsigned为例。

但是,请注意,这对您的bigint类提出了很高的要求,也就是说,它应该能够在编译时执行所有需要的计算,而这可能要困难得多。但是,这显然是您问题的固有要求。

UPD :刚刚注意到您的实际问题确实询问编译时计算,只是enum - 就像语法一样。但那时更容易做到:

template<std::uintmax_t num>
struct factorial
{
    static bigint calc_value()  { /* same code */  }
    static const bigint value;
};

template<std::uintmax_t num>
const bigint factorial<num>::value = factorial<num>::calc_value();

如果您使用int(或类似)代替std::uintmax_t,这甚至可以与c ++ 03兼容。