2015-12-29 44 views
0

我試圖使用一些可變參數模板參數,但我很快被我沒有設法理解的錯誤所阻止。C++多變量模板不綁定到函數參數

#include <tuple> 

template <typename T> 
struct Foo 
{ 
    typedef T type; 
}; 

// return a tuple of pair of args and Foo templated on Types 
template <typename Head, typename ...Args, typename Type, typename ...Types> 
auto func(Head arg, Args... args) 
{ 
    return std::tuple_cat(std::make_tuple(std::make_pair(arg, Foo<Type>())), 
         func<Args..., Types...>(args...)); 
} 

template <typename Head, typename Type> 
auto func(Head arg) 
{ 
    return std::make_tuple(std::make_pair(arg, Foo<Type>())); 
} 

int main() 
{ 
    func<int, bool, char>(1, 2, 3); 
} 

這裏FUNC試圖解開模板參數,使一對FUNC論證的元組和一個Foo結構模板在第二可變參數模板,但我有:

test.cc:25:3: error: no matching function for call to 'func' 
func<int, bool, char>(1, 2, 3); 
^~~~~~~~~~~~~~~~~~~~~ 
test.cc:11:6: note: candidate template ignored: couldn't infer template argument 'Type' 
auto func(Head arg, Args... args) 
^ 
test.cc:18:6: note: candidate function template not viable: requires single argument 'arg', but 3 
    arguments were provided 
auto func(Head arg) 
^ 
1 error generated. 

爲什麼類型不能爲推斷 ? (海灣合作委員會告訴我一樣)

我確信在sed :: tuple_cat實現(https://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-api-4.5/a01066_source.html)之後可以使用多個可變參數模板,我認爲這是一個簡單的例子,如果有解決方案,或者如果標準不接受這一點。

感謝您的幫助,

+1

它應該推斷爲什麼?你告訴它'Head'和2'Args',並給出了它們各自的函數參數。 'Type'不在那裏使用,所以它不可能被推斷出來。 – chris

回答

2

推導出最後一個參數。

...模板參數是貪婪的 - 它們將消耗傳遞參數並且不會爲以後的模板參數「保存」任何參數。

一旦完成,扣除發生從非模板函數參數。

交換這樣的:

template <typename Type, typename ...Types, typename Head, typename ...Args> 
auto func(Head arg, Args... args) 

而且,擺脫對方超負荷,所以func<int,int>(3)一點也不含糊。

這使得遞歸突破,但很容易解決:

template <class... Types, class... Args> 
auto func(Args... args) 
{ 
    return std::make_tuple(std::make_pair(args, Foo<Types>())...); 
} 

其中有是很好的和短的獎金。

+0

其實我只需要在1個類型上模板Foo,所以第二個版本不起作用。 而第一個仍然ambigous。它似乎不想解壓縮...參數 – yayg

+0

@yayg我只在第二個示例中一次性傳遞'Foo' ...包擴展對錶達式起作用。 – Yakk

+0

非常感謝!我不知道這個真棒功能:D – yayg

0

的關鍵數據這裏的一點是,可變參數的參數將一個空的列表相匹配。這有幾個後果。

第一個後果是,給下面的模板聲明:

template <typename Head, typename ...Args, typename Type, typename ...Types> 

及以下實例:

<int, bool, char> 

有幾種方法的實例可以匹配模板:

1 。

Head   int 
...Args  bool 
Type   char 
... Types  (empty list) 

2.

Head   int 
...Args  (empty list) 
Type   bool 
... Types  char 

所以,這就是不確定性的來源之一。 main()中的參考可以匹配模板定義。儘管在某些情況下可以解決這種模糊問題有各種神祕規則,但總是最好不要依賴神祕的模板消歧規則,或者至少不要再使用幾種標準的基本方法。

但是,回到主題上,編譯器將在這裏落後八球,但沒有明確的候選人來解決main()中的模板引用。但情況變得更糟。鑑於

auto func(Head arg, Args... args) 

auto func(Head arg) 

因爲,再一次,一個variatic參數,在這種情況下,它Args...,可以匹配空列表,然後,例如:

func(4) 

能匹配任一功能簽名。

將所有這些因素結合在一起,編譯器無法在這裏真正做出正面或反面。