[英]Constexpr, templates and array size
我想将模板参数传递给函数调用,返回值用作数组的大小即
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;
}
编译器错误:
~ $ 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
知道怎么解决这个问题吗?
在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))));
}
如果要计算2^N
,可以键入:
pow<N>(2)
注1:这个元函数非常通用,也适用于负整数和浮点类型,所以你可以输入: pow<-3>(3.14)
注2:模板中N>1
或N<0
的乘法在此处阻止无限递归,并在分支不相关时强制模板参数等于零。 这可以通过模板特化来完成,但这里使用的技术允许编写单个函数。
在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;
}
编辑:转到理查德史密斯的更聪明的答案。
根据您接受的答案,没有必要使用元函数将myPow
算法实现为constexpr
myPow
函数。
您可以默认指数参数= 0然后:
constexpr int myPow(int a, int b = 0){
return b == 0 ? 1 : myPow(a,b - 1) * a;
}
如果你不喜欢默认那个参数,那么你可以在myPow
刚调用的constexpr
辅助中默认该参数,例如
namespace impl {
constexpr int myPow(int a, int b = 0){
return b == 0 ? 1 : myPow(a,b - 1) * a;
}
}
constexpr int myPow(int a, int b){
return impl::myPow(a,b);
}
如果你至少升级到gcc 4.7.2你甚至可以使用-std=c++11
来隐藏myPow
本身内的辅助,因为你可以在constexpr
函数体内定义类型:
constexpr int myPow(int a, int b){
struct _1 {
static constexpr int _2(int a, int b = 0) {
return b == 0 ? 1 : _2(a,b - 1) * a;
}
};
return _1::_2(a,b);
}
(虽然我认为严格来说这个纬度是C ++ 1y扩展)。
您可能希望调整Vincent的优越算法,使其不再是N
的元函数,但仍然是算术类型的通用算法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.