Constexpr,模板和数组大小

tom*_*tom 4 c++ templates c++11

我想将模板参数传递给函数调用,返回值用作数组的大小即

constexpr int myPow(int a, int b){
  int result = 1;
  for(int i=0;i<b;i++)
    result *= a;
  return result;
}

template <int N>
class testClass{
public:
  testClass(){}
  int array[myPow(2,N)];
};

int main(){
  testClass<3> A;
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译器错误:

~ $ g++-4.6 test.cpp -std=gnu++0x
test.cpp: In function ‘constexpr int myPow(int, int)’:
test.cpp:6:1: error: body of constexpr function ‘constexpr int myPow(int, int)’ not a return-statement
test.cpp: At global scope:
test.cpp:12:23: error: array bound is not an integer constant before ‘]’ token
Run Code Online (Sandbox Code Playgroud)

知道怎么解决这个问题吗?

Vin*_*ent 7

在C++ 11中,constexpr函数只能包含一个return语句(有关完整的详细信息,请参见此处),因此您的myPow函数不符合constexpr(因为它包含一个for循环).

您可以使用此元函数在编译时计算整数幂:

template <int N, typename Type> 
constexpr Type pow(const Type& x) 
{
    return (N > 1) ? (x*pow<(N-1)*(N > 1)>(x)) 
                   : ((N < 0) ? (static_cast<Type>(1)/pow<(-N)*(N < 0)>(x)) 
                              : ((N == 1) ? (x) 
                                          : (static_cast<Type>(1))));
}
Run Code Online (Sandbox Code Playgroud)

如果要计算2^N,可以键入:

pow<N>(2)
Run Code Online (Sandbox Code Playgroud)

注1:此元函数非常通用,也适用于负整数和浮点类型,因此您可以键入: pow<-3>(3.14)

注2:模板中N>1或N<0在模板中的乘法是为了阻止无限递归,并在分支不相关时强制模板参数等于零.这可以通过模板特化来完成,但这里使用的技术允许编写单个函数.


Ric*_*ith 7

在C++ 11中,constexpr函数非常受限制,并且您的代码不符合限制(您不能声明变量,改变本地状态,也不能使用大多数形式的语句 - 包括循环).但是,C++ 1y删除了大多数限制,而Clang 3.3在其-std=c++1y模式下接受原始代码示例.

如果您需要代码在C++ 11模式下工作,您可以重写它以回避constexpr限制:

constexpr int myPow(int a, int b) {
  return b ? a * myPow(a, b - 1) : 1;
}
Run Code Online (Sandbox Code Playgroud)