Constexpr,模板和数组大小
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
限定函数。
您可以默认指数参数 = 0,然后:
constexpr int myPow(int a, int b = 0){
return b == 0 ? 1 : myPow(a,b - 1) * a;
}
如果您不喜欢默认该参数,那么您也可以默认该参数在constexpr
辅助myPow
只是调用,例如
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扩展(。
您可能希望调整文森特的卓越算法,以便它在N
中不再是一个元函数,但在算术类型。
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 如何将临时 C 数组传递到 constexpr 容器中
- 任意大小的 constexpr 数组是否可以用作 switch 语句中的案例?
- C++:初始化 constexpr 构造函数中的成员数组
- C++访问静态 constexpr 数组
- 在 constexpr 构造函数中初始化数组是否合法?
- 从非类型模板参数声明 constexpr 数组的可移植方法
- 编译时生成应在构造函数中创建的非 constexpr 对象数组
- C++编译时使用 constexpr 字符数组指针分配静态数组?
- 我可以使用 constexpr 函数声明一个静态数组吗?
- 将constexpr字节数组与缓冲区的一部分(指向数据的指针)进行比较
- 正在初始化函数指针的constexpr数组
- constexpr数组初始化
- 类本身内部的类对象的静态constexpr数组
- const(但不是constexpr)用作内置数组大小
- 使用模板函数初始化 constexpr 数组
- 用另一个 constexpr 数组对成员数组进行大括号初始化
- C++ constexpr:在编译时计算标准数组
- 如何将constexpr数组传递到函数中
- 将`constexpr`与数组初始化