2013-04-17 40 views
3

我正在學習STL和模板。這是我的問題。我寫這個函數的兩個迭代器「之間」計算元素的總和:STL容器的C++函數模板專業化

template <typename Iter> double PartialSum(Iter itBegin, Iter itEnd){ 
    if (itBegin == itEnd) return 0.; 
    double dSum = 0; 
    while(itBegin != itEnd){ 
     dSum += (*itBegin); 
     ++itBegin; 
    } 
    return dSum; 
} 

而且這工作正常(我知道我可以使用std::accumulate但這是學習的目的)。現在,我想有相同的功能的std:map但迭代器有不同的工作比在std::vectorstd::list的情況。因此,我想寫超載/專用PartialSum。我嘗試和失敗是這個(小例子):

template <typename T1, typename T2> double PartialSum(std::map<T1,T2>::iterator itBegin{ 
    return 0.; 
} 

這是錯誤日誌:

Main.cpp(42): error: nontype "std::map<_Key, _Tp, _Compare, _Alloc>::iterator [with _Key=T1, _Tp=T2, _Compare=std::less<T1>, _Alloc=std::allocator<std::pair<const T1, T2>>]" is not a type name template <typename T1, typename T2> double PartialSum(std::map<T1,T2>::iterator itBegin){ Main.cpp(83): error: no instance of overloaded function "PartialSum" matches the argument list argument types are: (std::_Rb_tree_iterator<std::pair<const std::string, int>>) std::cout<<"Map partial sum: "<<PartialSum(myMap.begin())<<std::endl; 

由於它是如此簡單,我可能不undersatnd一些非常基本的。會很樂意聽聽你的意見:-)

+2

你不小心刪除一半的線路?您尚未完成專業化的參數編寫。 –

+0

另一方面,你不能部分專門化一個功能。 (這是一個重載,而不是專門化)你應該使用一個模板函數來調用模板類中的一個靜態函數。這可以讓你部分專業化。 –

+0

你是什麼意思*失敗*?編譯錯誤?一些意外的運行時行爲 – Gorpik

回答

2

試圖以另一種方式來制定。

考慮你有功能

template<typename T> 
T f(){ 
    return T(); 
} 

這是不可能在這裏自動獲得T,所以你需要把它作爲f<T>()。同去同

template <typename T> 
int f(typename type<T>::inner){ 
    // 
} 

舉例來說,如果你有

struct type{ 
    typedef int inner; 
} 

很容易看到這裏,如果你調用f(0)這是不可能得到T.
你可能會說這是可能得到它在那個特殊的情況下,map,但你將如何定義它?

你應該閱讀C++標準閱讀哪種類型應該是deducable。


就您的情況,您可以在以下方式

PartialSum<std::string, int>(m.begin()); 

BTW,看來,這地圖只是罕見的情況下,你可以嘗試做一些更普遍呼籲,將工作與任何迭代器類型。您可能會看到std::accumulate來源獲取一些想法。

template<typename _InputIterator, typename _Tp, typename _BinaryOperation> 
inline _Tp 
accumulate(_InputIterator __first, _InputIterator __last, _Tp __init, 
     _BinaryOperation __binary_op) 
{ 
    // concept requirements 
    __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) 
    __glibcxx_requires_valid_range(__first, __last); 

    for (; __first != __last; ++__first) 
__init = __binary_op(__init, *__first); 
    return __init; 
} 
+0

@ RiaD:你能否以某種方式重新配置?我真的很想理解這件事,我發現你的答案中有些東西,但我沒有完全理解。 –

+0

@SimonRighley嘗試結帳 – RiaD

+0

@ RiaD:正確的點。太棒了,它的工作原理,我明白爲什麼現在。太感謝了! :) –

-2

當取消引用std::map<T1, T2>::iterator,你會得到一個std::pair<const T1, T2>,其中.first元素是關鍵,而.second元素的值。

一般結構是這樣的:(未測試的代碼,甚至未編譯)

template <typename T1, typename T2> double PartialSum(std::map<T1,T2>::iterator itBegin, std::map<T1,T2>::iterator itEnd) 
{ 
double dSum = 0; 
while(itBegin != itEnd){ 
    dSum += (itBegin->second); 
    ++itBegin; 
} 
return dSum; 
} 
+0

OP甚至不試圖解引用迭代器。 – Gorpik

+0

是的,確切地說。我原來的代碼和Marshall Clow發佈的代碼一樣,並沒有工作。然後,我將其降至最低限度以縮小問題的根源。 –

1

除此之外,T1和T2是不抵扣的問題,還有就是你錯過了typename關鍵字在從屬名稱

template<typename T1, typename T2> 
void MyFunction(typename std::map<T1, T2>::iterator it /*, ...*/) 
//    ^^^^^^^^^   

你看到另一個問題,一個從屬名稱是名稱取決於模板參數。的確,理論上可能有這樣的類型T1和T2,name map :: iterator不是一個類型,而是一個靜態數據成員。編譯器將始終假定數據成員,除非您明確指定它是一種類型。

您應該簡單地做這樣的事

template<class ValueType, class IteratorType, class Func> 
ValueType partialSum(IteratorType first, IteratorType last, ValueType startingValue = ValueType(), Func func = std::plus<ValueType>()) 

,這將覆蓋所有的情況。要彙總地圖,您需要提供添加兩對的func。

+1

沒有,這不是主要的問題http://ideone.com/xPZdkE – RiaD

+0

@RiaD:的確,謝謝 –

+0

究竟RIAD,一個錯誤,當我補充說消失了,但是編譯器錯誤「重載函數沒有實例「PartialSum」匹配參數列表「仍然存在。 –