2014-09-06 153 views
3

我寫一個使用可變參數爲模板的功能,像這樣一個圖書館:的可變參數模板顯式實例化功能

template<typename ... T> 
void func(T ... args) { 
    // ... 
} 

我需要確保在該函數中生成的代碼(即顯式實例化)的某些類型,像這樣:

template class func<int>; 
template class func<int, int>; 
template class func<int, int, int>; 
// ... 

其中int參數的最大數是一個非const maxArgs()(我無法改變這個,因爲它是一個外部函數)。我試過以下內容:

template<typename ... T> 
void f(size_t max, T ... args) { // Generates "infinitely" 
    if (sizeof...(T) < max) { 
    func(args...); 
    f(max, args..., 0); 
    } 
} 

int main(int argc, char** argv) { 
    f(maxArgs(), 0); 
    // ... 
    return 0; 
} 

但是,編譯器對函數生成遞歸沒有適當的基本情況,所以無法編譯。我已經使用非類型模板,像這樣(使用一些代碼here)也試過:

template<int ...> struct seq { }; 
template<int N, int ... Ns> struct gens : gens<N-1, N-1, Ns...> { }; 
template<int ... Ns> struct gens<0, Ns...> { typedef seq<Ns...> type; }; 

std::vector<int> params; 

template<int ... Ns> 
void f(seq<Ns...>) { 
    test(std::get<Ns>(params)...); 
} 

void instantiate(size_t max) { 
    for (int i = 1; i < max; ++i) { 
    for (int j = 0; j < i; ++j) { 
     params.push_back(0); 
    } 
    f(typename gens<i>::type()); // Fails to compile -- i is not const 
    params.clear(); 
    } 
} 

int main(int argc, char** argv) { 
    instantiate(maxArgs()); 
} 

但這需要一個常量的值,所以無法編譯爲好。有沒有辦法正確地做到這一點,不知道maxArgs()的返回值?

+0

鑑於這可能是不可能的,編譯器(特別是gcc)如何使用省略號和va_list處理C風格變量參數函數的代碼生成?例如:'void func(int a,...){...}' – 2014-09-06 08:55:53

回答

0

因爲我知道maxArgs()(即42)有一個最大可能值,所以我想出了以下解決方案,這要歸功於@JohnZwinck的建議。

#include <vector> 

typedef void (*void_fnptr)(); 

std::vector<void_fnptr> table; 

// Function that needs to be code-generated for certain number of int types 
template<typename ... T> 
void func(T ... args) { 
    // ... 
} 

template<typename T> 
void instantiate(T elem) { 
    table.push_back((void_fnptr)func<T>); 
} 

template<typename T, typename ... Ts> 
void instantiate(T first, Ts ... rest) { 
    table.push_back((void_fnptr)func<T, Ts...>); 
    instantiate(rest...); 
} 

int main(int argc, char** argv) { 
    // 42 int arguments: 
    instantiate(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 
       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); 
    // ... 
    return 0; 
} 
1

不,您不可能在編譯時生成取決於僅在運行時已知的值的模板。你需要選擇一些預先保持不變的最大值(有時候不要使用所有的實例),或者想辦法讓maxArgs()成爲編譯時常量。或者在使用時即時編譯您的代碼!

由於您對此代碼的信息比我們做得更多,因此您可能會考慮是否將其作爲可變參數模板實際上是需要的。它似乎不是,因爲模板參數的數量是在運行時確定的。編寫一個完全運行時確定的解決方案可能會更好,但沒有可變參數模板。

+0

所以我需要以這種方式生成代碼的原因是我必須爲另一個庫提供各種實例的函數指針'func',不知道應用程序將使用我自己的庫來使用哪些特定的實例。此外,我傳遞函數指針的庫負責'maxArgs()'。 – 2014-09-06 08:46:40

+0

'maxArgs()'的允許範圍是多少?根據您需要如何給它指定函數指針,其他庫的確切要求是什麼?它是否可以接受指向C風格可變參數函數的指針(如printf),還是需要指向常量函數的指針,取1..maxArgs參數?如果是後者,那麼這樣的圖書館如何被正確地使用?這似乎很難想象。 – 2014-09-06 09:00:17

+0

可能的範圍是'8 <= maxArgs()<= 42'。該庫以函數指針數組的形式獲取函數,其中類型必須類型轉換爲void(* fn)()';這些函數不需要模板,並且可以使用C風格的可變參數函數 – 2014-09-06 14:21:03