2012-02-21 70 views
1

我想寫一個通用的平均算法。也就是說,對於任何具有運算符+(T)和運算符/(浮點數)的類型T,我想找到容器中T的平均值:平均小型

類似這樣的工作對浮點類型工作正常:

template<typename T> 
typename T::value_type RunningAverage(const T& v) 
{ 
    typename T::value_type vectorRunningAverage = 0; 

    for(unsigned int i = 0; i < v.size(); ++i) 
    { 
    vectorRunningAverage = (v[i] + i*vectorRunningAverage)/(i+1); 
    } 

    return vectorRunningAverage; 
} 

我可以改變

typename T::value_type vectorRunningAverage = 0; 

float vectorRunningAverage = 0; 

,然後它會用工作鍵入像無符號字符(不能添加多個無符號字符並將結果存儲在無符號字符中而不溢出),因爲它可以隱式轉換爲浮點型。然而,如果我有一些更復雜的類型(比如我想平均一個std::vector<std::vector<unsigned char> >中的組件,這是行不通的。有沒有我丟失的東西?或者這樣做沒有意義嗎?

回答

1

我想你應該告訴對方明確提所需的返回類型:

template<typename T, typename ResultT = typename T::value_type> 
ResultT RunningAverage(const T& v); 

我也覺得你應該開始&結束迭代器而不是整個容器,因爲它會使你的函數更通用(你可以得到前半部分的平均值或者例如)。

+0

提供返回類型作爲模板參數的好主意。通過這種方式,我可以對不可變的類型(即來自庫或STL容器樣式類型的類型)做類似的事情。 另外,好吧,我會讓它採用迭代器。 – 2012-02-21 02:31:07

2

因此,你需要以某種方式定義您的T類型是什麼含T值的平均值的類型是什麼。

C++特性提供清潔和非侵入的解決方案。

template <class T> 
struct average 
{ 
    typedef float type; // could be or could be not sane default, depends on the domain 
}; 

然後,針對各類需要「微調「你只需提供的專業化(部分或全部) 10模板:

template <> 
struct average<double> 
{ 
    typedef double type; // want more precision 
}; 

template <class T> 
struct average<MyMegaType<T> > 
{ 
    typedef MyMegaType<T>::value_type type; 
}; 

比你的函數的sgnature可能是

template<typename T> 
typename average<T::value_type>::type RunningAverage(const T& v); 
+0

謝謝亞歷山大。這將適用於我定義的類型,如MyMegaType,但對於我無法更改的類型(即來自庫的類型或從我的平均矢量>的示例中,不可能添加'typedef ... type'to vector 。我想我會和John Zwinck的解決方案通過另一個模板參數提供返回(和內部)類型 – 2012-02-21 02:32:44

+0

我認爲你沒有得到它。不向'vector '添加任何東西來爲它創建'average'特性。特性的美妙之處在於yo *不需要*改變現有類型來添加這個typedef - 你只需爲這些類型定義專門化。 – 2012-02-21 10:30:54

+0

我認爲你是對的,我確實錯過了特徵的想法。我試過這個:http://ideone.com/fZ26B但是我得到這個錯誤:錯誤:沒有匹配調用'(average ) (std :: vector &)'。任何建議嗎? – 2012-02-21 12:20:13