是否可以从模板函数参数中推导出非类型模板参数?
考虑这个简单的模板:
template <int N> constexpr int factorial()
{
return N * factorial<N - 1>();
}
template <> constexpr int factorial<0>()
{
return 1;
}
template <> constexpr int factorial<1>()
{
return 1;
}
我希望能够更改factorial
,以便我可以这样称呼它:
factorial(5);
让编译器在编译时计算出N的值。 这可能吗?也许有一些奇特的C ++ 11添加?
答案 0 :(得分:8)
您当前的代码通常写成如下,我相信:
constexpr factorial (int n)
{
return n > 0 ? n * factorial( n - 1 ) : 1;
}
如果使用常量表达式(例如factorial(5)
)调用它,那么所有编译器魔法都将起作用。但是如果你做int a = 3; factorial(a)
,那么我认为它将依赖于传统函数 - 即它不会构建一个预先计算出的答案的查找表。
通常,如果可以,您应该将每个函数和构造函数标记为constexpr
。如果有必要,编译器会将其视为正常函数。
答案 1 :(得分:5)
除非你有时间机器,否则无法完成。
该函数的参数在运行时处理。是的,在你的情况下,它是一个字面常量,但这是一个特例。
在函数定义中,参数 types 在编译时是固定的(因此,可用于推导模板参数),但参数 values 仅在运行时。
你为什么需要这个?是不是你不必输入<>
?
答案 2 :(得分:1)
我认为你不能那样做;唯一可行的方法是使用constexpr
函数参数作为模板版template
的{{1}}参数传递,但factorial
函数参数不被录取。
答案 3 :(得分:0)
不,这是不可能的,除非你想创建一个巨大的switch语句:
int getFactorial( const int v )
{
switch ( v )
{
case 1 : return factorial<1>();
case 2 : return factorial<2>();
//etc
default:
;
}
return 0;
}
答案 4 :(得分:0)
不,你不能这样做。模板参数只能从函数参数的类型中推导出来,而不能从值推断出来,这通常在编译时是不可知的。
当然,您可以将factorial
重写为非模板constexpr
函数;然后,如果参数已知,那么它将在编译时进行评估。
答案 5 :(得分:0)
使用邪恶的宏:
#define factorial(X) factorial<X>()