2012-11-24 200 views
2

通過我實現了Python的連鎖功能的C++相當於前一段時間由於可變參數模板。該函數用於連續遍歷許多容器。下面是使用一個名爲ChainedObject發電機的功能,不管它是舊的工作版本:類型推演和論證與可變參數模板模板

template<typename... Iterables> 
auto chain(Iterables&&... iters) 
    -> ChainObject<Iterables...> 
{ 
    return /* ... */; 
} 

和相應的主:

int main() 
{ 
    std::vector<int> vec = { 1, 2, 3, 4, 5 }; 
    std::list<int> li = { 6, 7, 8, 9, 10, 11, 12, 13 }; 
    for (auto& i: chain(vec, li)) 
    { 
     // You can edit a range of iterables 
     // as if there was only one of them. 
     i *= 5; 

     std::cout << i << std::endl; 
    } 
    return 0; 
} 

這主要工作得很好。我們不在乎ChainObject中存在什麼問題,所以讓我們來看看它。我試圖用模板模板,以確保所使用的不同集合有同樣的value_type和修改功能chain方式如下:

template<typename T, template<typename...> class... Iterables> 
auto chain(Iterables<T>&&... iters) 
    -> ChainObject<T, Iterables...> 
{ 
    return /* ... */; 
} 

我認爲這會做的伎倆,以確保我以前主要的listvector共享相同的類型,而是,我從GCC 4.7.1以下錯誤:

In function 'int main()':

error: no matching function for call to 'chain(std::vector&, std::list&)'

note: candidates are:

note: ChainObject<T, Iterables ...> chain(Iterables<T>&& ...) [with T = int; Iterables = {std::vector, std::list} ]

note: no known conversion for argument 2 from ' std::list<int> ' to ' std::list<int>&& '

note: ChainObject<T, Iterables ...> chain(Iterables<T>&& ...) [with T = int; Iterables = {std::vector, std::list}]

note: no known conversion for argument 2 from ' std::list<int> ' to ' std::list<int>&& '

error: unable to deduce 'auto&' from ''

看來,問題來自於通過採取右值引用的函數的參數。但是,我真的不明白爲什麼我的第一個版本運行良好,並注意使用模板模板。

+0

您是否嘗試過通過左值引用,而不是右值嗎? –

+0

請勿將模板模板與容器組合使用。一旦使用分配器就會失敗。只需檢查嵌套的'value_type'是否相等。 – pmr

回答

5

你的問題是T&&模板魔術僅適用於類型參數(它的工作方式推導T作爲例如int&如果需要的話 - 對於左值參數)。 X必須在這種情況下,一個類模板,而不是像「參考到類模板」 - 它不能爲模板模板參數,在實際的類型是X<T>&&工作。所以最後你必須傳遞一個右值引用,你不能從一個左值(變量)中隱式地得到。這就是說,我建議你恢復到以前的代碼,並檢查value_type與SFINAE是否相同(或兼容,等等,不管你會怎麼做)。

粗碼草圖(嚴格平等):

template <class ... Ts> struct all_types_equal 
{ 
    static const bool value = false; 
}; 

template <class T> 
struct all_types_equal<T> 
{ 
    static const bool value = true; 
}; 
template <class T, class ... Rest> 
struct all_types_equal<T, T, Rest...> 
{ 
    static const bool value = all_types_equal<T, Rest...>::value; 
}; 

template<typename... Iterables> 
auto chain(Iterables&&... iters) 
    -> typename std::enable_if<all_types_equal<Iterable::value_type...>::value, ChainObject<Iterables...> >::type 
+0

非常感謝。看來我仍然有很多要學習C++。我會恢復到使用普通的舊'enable_if'然後:) – Morwenn

+0

我想,一個正確的返回類型'類型名稱的std :: enable_if ::類型:: value_type的... > :: value,ChainObject > :: type'。 – Morwenn