2015-01-10 44 views
-1

對於家庭作業,我必須創建一個模板化的標準差功能,可以在任何容器上執行。下面是我有:所有容器都有.size()函數嗎?

template <typename Container> 
double findMean(Container c, int count){ 
    double sum = 0; 
    for (auto&& e : c){ 
     sum += e; 
    } 
    sum /= count; 
    return sum; 
} 

template <typename Container> 
double findStDev(Container c){ 
    double mean = findMean(c, c.size()); 
    std::cout << mean << std::endl; 
    for (auto&& e : c){ 
     e -= mean; 
     e *= e; 
    } 
    mean = sqrt(findMean(c, c.size())); 
    return mean; 
} 

我第一次發現意味着我要在容器(n)的全尺寸來劃分,但是當我發現它的標準差,第二次,我需要除以大小1(n-1)。

.size()函數是否可用於所有C++容器?

+0

除了內建數組之外,它可用於所有。 [現在](http://www.open-std.org/Jtc1/sc22/wg21/docs/papers/2014/n4017.htm) – tux3

+1

順便說一句,你不需要':: size'來計算平均值。 – tumdum

回答

6

差不多。根據表96 - N3797中的容器要求,標準庫中的所有容器必須提供成員函數size。它應該有恆定的執行時間並返回distance(a.begin(),a.end())的值爲一個容器a

然而,提到的後面上的一個(並且僅一個)異常:

甲修飾符Modifiers滿足所有的容器(表96)的要求,不同之處在於尺寸()成員 函數是不提供。

(N3797 23.3.4.1第2項目)

這意味着,std::forward_list確實是一個標準容器,做有一個成員函數size

2

在STL的古老傳統中,您可以讓您的模板接受一對前向迭代器並計算總和元素的距離。

#include <cstddef> 
#include <iterator> 

template<typename FwdIter, 
     typename value_type = typename std::iterator_traits<FwdIter>::value_type> 
value_type 
mean(const FwdIter begin, const FwdIter end) 
{ 
    std::size_t count {0}; 
    value_type sum {}; 
    for (auto it = begin; it != end; ++it) 
    { 
     sum += *it; 
     ++count; 
    } 
    return sum/count; 
} 

這將適用於標準庫容器,數組,指針,無論你想要什麼。對於容器,您可以簡單地定義便利性轉發模板,如果需要,可以調用cbegincend

請注意,我已經排除了上述示例中的任何類型限制。在實踐中,您應該僅在std::is_arithmetic<value_type>等特殊條件下才能使用std::enable_if模板。

+0

另請注意,這種方法經常被忽略的一個優點是,您可以在不是容器的範圍內運行算法,它可以是一對*輸入迭代器*,也可以是容器的子集(例如平均值最高10%的參賽作品)。 +1 –

2

是否所有的容器都有.size()函數?

不是,他們大部分都是,在C++ 11之前,他們都做了。但是,C++ 11看到了單鏈表列表模板std::forward_list的引入,其中不是有一個size()成員函數。所有其他容器都這樣做,並且當前標準指定算法複雜度爲O(1)。 Pre-C++ 11,std::list被允許具有線性複雜度。

+0

'std :: forward_list'不符合容器的要求(參見N3797 23.3.4。1第2條:「除了沒有提供size()成員函數外,forward_list滿足容器的所有要求(表96)」),所以雖然在第23段(容器庫)中有所描述,但它不是標準意義上的容器。這是錯的嗎? –

+0

@BaummitAugen它是一個標準庫序列容器(「一個forward_list是一個容器,它支持前向迭代器...」)在需求中只有一個例外(就像曾經用於'std :: list'一樣)。 – juanchopanza

+0

好的,謝謝。由於我無法刪除我的答案,因爲它被接受了,所以我會在編輯時更正它。 –

相關問題