簡體   English   中英

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>1N<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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM