2011-08-18 24 views
4

我知道sizeof...(Args...)產生的C++ 0x被壓縮的模板參數列表中的類型數量,但我想實現它用於演示目的的其他功能,但它不會編譯。簡單的可變參數模板函數不能立即

// This is not a solution -- overload ambiguity. 
// template <typename... Args> size_t num_args();   // Line 7 
// template <> 
constexpr size_t num_args() 
{ 
    return 0; 
} 

template <typename H, typename... T> 
constexpr size_t num_args()        // Line 16 
{ 
    return 1 + num_args <T...>(); // *HERE* 
} 

int main() 
{ 
    std :: cout << num_args <int, int, int>(); 
} 

此錯誤在*HERE*

No matching function call to ... 
... candidate is template<class H, class ... T> size_t num_args() 

即它沒有看到其首先定義的基本情況。向前聲明template<typename...T>num_args();在重載解析中引入了歧義。

x.cpp:30:45: note: candidates are: 
x.cpp:7:36: note: size_t num_args() [with Args = {int, float, char}, size_t = long unsigned int] 
x.cpp:16:9: note: size_t num_args() [with H = int, T = {float, char}, size_t = long unsigned int] 

我使用的是gcc 4.6。我該如何做這項工作?

謝謝。

回答

7

您沒有申報基本情況。您的num_args函數有一個無模板超載,但在調用函數num_args<T...>()時,將永遠不會找到該函數,原因很明顯:它總是嘗試實例化函數模板

然而,您可以專門您的功能模板來執行所需的操作。

template <> 
constexpr size_t num_args<>() 
{ 
    return 0; 
} 

然而,這是不行的,因爲無論是在這裏你專業無參數的函數模板,這樣的模板不存在:你的其他函數模板num_args總是至少有一個說法,H

爲了真正做到這一點,您需要部分專業化,而這些專業化僅適用於類模板。所以這就是你在這裏所需要的。

template <typename T> 
struct num_args_t; 

template <> 
struct num_args_t { 
    static size_t const value = 0; 
}; 

template <typename H, typename T...> 
struct num_args_t { 
    static size_t const value = num_args_t<T...>::value + 1; 
}; 

template <typename T...> 
constexpr size_t num_args() { 
    return num_args_t<T...>::value; 
} 
+0

(未經測試,順便說一下) –

+0

謝謝,但我不明白爲什麼它的問題是「其他函數模板總是至少有一個參數H」 - 想象我的帖子的前兩行不註釋 - 何時遞歸到'num_args ()'與空'Args ...'當然應該匹配基本情況?!?!? 「安全printf」示例還能如何工作? – spraff

+0

@spraff再次:你不*有一個基本情況。不存在函數'num_args ',它可能有這樣的基本情況。你有'num_args '但這是一個完全不同的函數:它至少有一個參數,所以一個帶有零參數的函數模板是*不是它的專門化。 –

4

康拉德的答案應該讓你去,但我認爲更地道的方式這樣的事情通常表示爲與靜態成員常量,所以我只是想呈現的解決方案:

#include <type_traits> 

template <typename...> struct arg_size; // no primary definition needed 

template <typename T, typename ...Args> struct arg_size<T, Args...> 
    : public std::integral_constant<std::size_t, 1 + arg_size<Args...>::value> { }; 

template <> struct arg_size<> 
    : public std::integral_constant<std::size_t, 0> { }; 

然後你通過arg_size<Args...>::value獲取參數包大小。

相關問題