2013-07-22 63 views
6

我目前正試圖讓我的頭可以用variadic模板支持來做一些事情。比方說,我有這樣的功能 -已知類型的C++可變參數函數模板

template <typename ... Args> 
void foo(Args ... a) 
{ 
    int len = sizeof...(tail); 
    int vals[] = {a...}; 
    /* Rest of function */ 
} 

/* Elsewhere */ 
foo(1, 2, 3, 4); 

此代碼的工作,因爲我事先假設的爭論將是整數,但很明顯,如果我提供別的東西將失敗。如果我知道的參數包將包含在事先特定的類型,有一些方法,我可以不用模板,並有一些像 -

void foo(int ... a) 

我試圖這樣做,但是編譯器給了一個錯誤關於foo是一個無效的領域。我知道我也可以通過遞歸訪問包中的參數,但我不確定這會解決我所遇到的問題 - 也就是說,我希望能夠獲取可變數目的相同類型的參數。

+1

你可以用'enable_if',以確保所有類型的*是*整數。 –

+2

如果你潛入一堆整數,代碼將起作用。如果你給它別的東西,它不起作用。看起來任務完成。哪裏有問題? –

+0

我想問題是在編譯時是否可以確保它們是整數。 – znby

回答

3

如果你知道之前的類型,你可以使用函數重載與std:initializer_list

#include <initializer_list> 
#include <iostream> 

void foo(std::initializer_list<int> l) 
{ 
    for (auto el : l) 
     // do something 
} 

void foo(std::initializer_list<float> l) 
{ 
} 

void foo(std::initializer_list<std::string> l) 
{ 
} 

int main() 
{ 
    foo({1, 2, 3, 4 }); 
    foo({1.1f, 2.1f, 3.1f, 4.1f }); 
    foo({ "foo", "bar", "foo", "foo" }); 
    return 0; 
} 

如果您使用Visual Studio 2012,您可能需要Visual C++ Compiler November 2012 CTP

編輯:如果你仍然想使用可變參數模板,你可以這樣做:

template <int ... Args> 
void foo() 
{ 
    int len = sizeof...(Args); 
    int vals[] = {Args...}; 
    // ... 
} 

// And 

foo<1, 2, 3, 4>(); 

但你要記住,它不與floatstd::string例如工作:你會'float': illegal type for non-type template parameter結束。 float作爲non-type template parameter不合法,這與精度有關,浮點數不能精確表示,並且您指的是相同類型的可能性取決於數字的表示方式。

+0

如果你需要知道編譯時的參數個數,這個解決方法還不夠,因爲'initializer_list'不提供'constexpr size()'成員。 AFAIK,沒有辦法用'is_same <>/is_convertible <>'檢查變量模板。 – user2523017

+0

@ user2523017你說得對,用這個解決方案我們在編譯時不能有參數個數。 –

1

我目前正試圖讓我的頭部可以用variadic模板支持做些事情。

假設你想與可變參數模板實驗,沒有發現任何解決您的問題,那麼我建議您看看下面的代碼:

#include <iostream> 

template<int ...Values> 
void foo2() 
{ 
    int len = sizeof...(Values); 
    int vals[] = {Values...}; 

    for (int i = 0; i < len; ++i) 
    { 
     std::cout << vals[i] << std::endl; 
    } 
} 

int main() 
{ 
    foo2<1, 2, 3, 4>(); 

    return 0; 
} 

foo2之間的區別你foo是您在運行時將參數傳遞給foo,並且在編譯時傳遞給foo2,因此對於您使用的每個參數集,編譯器都會生成單獨的foo2函數體。

10

這應該工作:

void foo(int); 

template<typename ...Args> 
void foo(int first, Args... more) 
{ 
    foo(first); 
    foo(std::forward(more)...); 
} 
+0

這個答案更適合OP要求的內容。這個解決方案唯一的缺點是遞歸部分。但現在我可以看到更好的解決方案,甚至不使用C++ 17和摺疊表達式。 – mic

相關問題