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

Dei*_*Dei 0 c++ enums templates c++11

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

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 };
};
Run Code Online (Sandbox Code Playgroud)

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

您可以像这样调用此函数: 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;
    }
};
Run Code Online (Sandbox Code Playgroud)

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

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

Pet*_*etr 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, "");
}
Run Code Online (Sandbox Code Playgroud)

现在,如果您希望通过旧语法访问它,您可以轻松地使用它

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, "");
Run Code Online (Sandbox Code Playgroud)

现场bigintunsigned例如着想.


但请注意,这对您的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();
Run Code Online (Sandbox Code Playgroud)

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

  • 实际上,我认为像`bigint`这样的类通常需要支持`constexpr`操作,即使在这个有点人为的问题之外:操作必然是非平凡的,并且可以对编译时提升持续评估.为了更快的程序,编译代码[更有趣](https://xkcd.com/303/).为此,`bigint`可能涉及一个大小模板参数,以避免需要内存分配. (2认同)