4

I would like to pass template argument to function call and the return value use as size of an array ie

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;
}

compiler errors:

~ $ 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

Any idea how to get around this?

4

3 回答 3

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))));
}

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

pow<N>(2)

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

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

于 2013-07-06T20:46:35.177 回答
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;
}
于 2013-07-06T22:35:46.887 回答
2

编辑:转到理查德史密斯更聪明的答案。

根据您接受的答案,没有必要使用元函数来将您的myPow算法实现为constexpr-qualified 函数。

您可以默认指数参数 = 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 扩展)。

您可能希望调整 Vincent 的高级算法,使其不再是 中的元函数N,但仍然是算术类型的通用 at。

于 2013-07-06T22:33:55.177 回答