2012-01-12 143 views
5

是否可以從模板函數參數中推導出非類型模板參數?推導非類型模板參數

考慮這個簡單的模板:

template <int N> constexpr int factorial() 
{ 
     return N * factorial<N - 1>(); 
} 

template <> constexpr int factorial<0>() 
{ 
     return 1; 
} 

template <> constexpr int factorial<1>() 
{ 
     return 1; 
} 

我希望能夠改變factorial,這樣我可以或者調用它是這樣的:

factorial(5); 

,讓編譯器弄不清值的N在編譯時。 這可能嗎?也許有一些奇怪的C++ 11添加?

+0

你爲什麼要這麼做? 'factorial'函數不接受任何參數。'factorial(5)'比正確的'factorial <5>()'有什麼好處? – 2012-01-12 15:01:14

+0

@CodyGray:我認爲這個想法是創建一個通用的'factorial'函數,如果它有一個編譯時間已知的表達式,就可以在編譯時計算結果,但如果輸入是運行時,也可以在運行時計算它一個正常的變量。 – 2012-01-12 15:02:51

+0

@Matteo:據我瞭解,由於表達式聲明爲「constexpr」,因此在運行時不會計算任何東西。無論如何,我不明白爲什麼會有任何問題通過「普通變量」而不是使用標準語法的問題。這裏的問題是「我怎樣才能避免輸入尖括號」,我不明白其動機。 – 2012-01-12 15:05:03

回答

4

不能完成,除非你有時間機器。

該函數的參數在運行時處理。是的,在你的的情況下它是一個字面常量,但這是一個特例。

在函數定義,參數類型被固定在編譯時(且因此,可用於推斷模板參數),但參數僅固定在運行時。

爲什麼你需要這個?是不是隻需要輸入<>就可以了?

+0

非常多,我有一個龐大的代碼庫調用幾個函數,我重寫爲模板。替換名字很簡單,但將所有'f(2,3,「abc」,true)'變成'f <2, 3, true>(「abc」)'有點棘手。 – pezcode 2012-01-12 15:08:37

+1

宏如何將f(2,3,「abc」,true)'轉換爲'f_impl <2, 3, true>(「abc」)'? – 2013-07-02 15:36:24

1

我不認爲你可以這樣做;唯一的方法是將constexpr函數參數作爲模板factorial模板版本的template參數傳遞,但不允許constexpr函數參數。

0

不,這是不可能的,除非你想創造一個巨大的switch語句:

int getFactorial(const int v) 
{ 
    switch (v) 
    { 
    case 1 : return factorial<1>(); 
    case 2 : return factorial<2>(); 
    //etc 
    default: 
     ; 
    } 
    return 0; 
} 
0

不,你不能這樣做。模板參數只能從函數參數的類型推導出來,而不是的值,這在編譯時通常不會被知道。

當然,您可以將factorial重寫爲非模板constexpr函數;那麼如果參數是已知的,那麼它將在編譯時被評估。

8

您當前的代碼通常會被寫成如下,我相信:

constexpr factorial (int n) 
{ 
    return n > 0 ? n * factorial(n - 1) : 1; 
} 

如果你有一個常數表達式調用它,如factorial(5),那麼所有的編譯器魔術將開始發揮作用。但如果你做int a = 3; factorial(a),那麼我認爲它會回落到一個傳統的功能 - 即它不會建立一個預先計算的答案的查找表。

一般來說,如果可以的話,您應該將每個函數和構造函數標記爲constexpr。你什麼都不會損失,如果需要的話,編譯器會把它當作一個正常的函數。

+1

我不知道那些constexpr作品選擇退出。不幸的是,代碼只是一個例子,我需要一個固定大小的數組在實際函數內部,所以我需要一個數組大小作爲參數的模板。 – pezcode 2012-01-12 15:29:46

+0

也許在編譯時建立模板函數的函數指針數組,然後在運行時查找它們? 'factorial [3](.. other args ..)' – 2012-01-12 15:52:32

+0

@pezcode:將析因轉換爲調用模板代碼的宏,Aaron:youd更好地構建結果數組 – 2012-01-12 15:53:11

0

使用一個邪惡的宏:

#define factorial(X) factorial<X>()