Deduce非类型模板参数

时间:2012-01-12 14:57:37

标签: c++ c++11 templates template-deduction

是否可以从模板函数参数中推导出非类型模板参数?

考虑这个简单的模板:

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添加?

6 个答案:

答案 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>()