对于家庭作业,我必须创建一个可以在任何容器上执行的模板化标准差函数。 这是我所拥有的:
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++ 容器?
几乎。根据表 96 - N3797 中的容器要求,标准库中的所有容器都必须提供成员函数size
。它应具有恒定的执行时间,并返回容器a
的 distance(a.begin(),a.end())
值。
但是,后面提到了一个(也只有一个)例外:
forward_list满足容器的所有要求(表 96),除了 size() 成员 未提供功能。
(N3797 23.3.4.1 条款 2)
这意味着std::forward_list
确实是一个没有成员函数size
的标准容器。
按照 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;
}
这将适用于标准库容器、数组、指针等任何您想要的内容。 对于容器,您可以简单地定义一个方便的转发模板,如果需要,该模板可以调用cbegin
和cend
。
请注意,我省略了上面示例中的任何类型约束。 实际上,您可能应该仅在特殊条件下std::enable_if
模板,例如 if std::is_arithmetic<value_type>
。
所有容器都有 .size() 函数吗?
不。他们中的大多数人都这样做了,在C++11之前,他们都这样做了。然而,C++11 引入了单链表类模板std::forward_list
,它没有size()
成员函数。所有其他容器都这样做,当前标准规定算法复杂度为 O(1)。在C++11之前,std::list
被允许具有线性复杂性。