【问题标题】:Do all containers have a .size() function?所有容器都有 .size() 函数吗?
【发布时间】:2015-01-10 22:28:10
【问题描述】:

对于家庭作业,我必须创建一个可以在任何容器上执行的模板化标准差函数。这是我所拥有的:

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),但是当我第二次找到它的标准差时,我需要除以 size-1(n-1 )。

.size() 函数是否适用于所有 c++ 容器?

【问题讨论】:

  • 它适用于除内置数组之外的所有内容。 For now
  • 顺便说一句,你不需要::size 来计算平均值。

标签: c++ math size containers standard-deviation


【解决方案1】:

几乎。通过表 96 - N3797 中的容器要求,标准库中的所有容器都必须提供成员函数size。它应该具有恒定的执行时间,并为容器 a 返回 distance(a.begin(),a.end()) 的值。

但是,后面会提到一个(也是唯一一个)例外:

forward_list 满足容器的所有要求(表 96),除了 size() 成员 没有提供功能。

(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::enable_if 模板,例如 if std::is_arithmetic&lt;value_type&gt;

    【讨论】:

    • 另请注意,这种方法的一个经常被忽略的优点是您可以在不是容器的范围内运行算法,它可以是一对 输入迭代器,或者它可以是容器的子集(例如,最高 10% 条目的平均值)。 +1
    【解决方案3】:

    所有容器都有 .size() 函数吗?

    没有。他们中的大多数都这样做了,在 C++11 之前,他们都这样做了。然而,C++11 引入了单链表类模板std::forward_list,它没有具有size() 成员函数。所有其他容器都这样做,并且当前标准指定算法复杂度为 O(1)。在 C++11 之前,std::list 被允许具有线性复杂度。

    【讨论】:

    • std::forward_list 不满足容器的要求(参见 N3797 23.3.4.1 第 2 条:“forward_list 满足容器的所有要求(表 96),除了 size() 成员没有提供函数。”),所以虽然它在第 23 段(容器库)中有描述,但它不是标准意义上的容器。这是错的吗?
    • @BaummitAugen 它是一个标准库序列容器(“A forward_list 是一个支持前向迭代器的容器......”)需求中有一个例外(就像以前的 @987654325 @.)
    • 好的,谢谢。由于我无法删除我的答案,因为它已被接受,我将在编辑中更正它。
    猜你喜欢
    • 2017-09-26
    • 2016-03-25
    • 1970-01-01
    • 2011-03-17
    • 1970-01-01
    • 1970-01-01
    • 2020-07-10
    • 2014-03-20
    • 1970-01-01
    相关资源
    最近更新 更多