现在我知道以下是如何工作的:
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
。
答案 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, "");
Live,bigint
为unsigned
为例。
但是,请注意,这对您的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兼容。