【问题标题】:Best practices: How to improve this code that sums container values?最佳实践:如何改进对容器值求和的代码?
【发布时间】:2010-11-29 18:37:25
【问题描述】:

我正在编写一个简单的函数,它遍历容器中的数字并计算一些汇总值(本例中的熵)。

我想把它写得尽可能通用,这样它就可以在不同的容器(vectorset,...)上使用不同的值类型(doublefloat,...) ,所以我这样做:

template<class Iterator>
typename Iterator::value_type Entropy(Iterator begin, Iterator end) {
  typedef typename Iterator::value_type Value;
  Value result = Value(); // assignment needed?
  for (Iterator it = begin; it != end; ++it) {
    result -= *it * log(*it);
  }
  return result;
}

我对这段代码根据所有最佳实践的样子感兴趣。换句话说,这个小函数的 STL 实现到底是什么样的?

【问题讨论】:

  • “所有最佳实践”的集合是如此的冲突,以至于永远无法编写代码。你到底是什么意思?
  • 我只是好奇 STL 的实现者是如何编写这个的。我想学习如何编写与 STL 代码本身一样简洁通用的代码...

标签: c++ stl


【解决方案1】:

查看 std::transform 和 std::accumulate

【讨论】:

  • 有趣,为什么transform (gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/…) 的源代码对值类型使用了一个额外的模板参数,而不是像我一样只使用Iterator::value_type
  • @user:您正在链接到accumulate。您可以选择一个初始值(例如,当所有值相乘时,1 为佳),结果类型不必与Iter::value_type 相同。
  • 因为您可能需要其他结果类型,例如从整数列表中计算平均值时,您仍然需要一个实值结果。
【解决方案2】:
template < typename T1, typename T2 >
T1 entropy_sum(T1 sum_so_far, T2 number)
{
  return sum_so_far - static_cast<T1>(number) * log(static_cast<T1>(number));
}
double entropy = std::accumulate(set.begin(), set.end(), 0.0, &entropy_sum<double, set_type::value_type>);

除了Value() 可能不是法律声明之外,您的方法还可以。

编辑以反映评论。

【讨论】:

  • 但是log 也是为floatlong double 定义的,所以我也想允许这些类型。
  • 然后参数化返回和第一个参数。在这种情况下,您还需要进行特定的转换,否则为整数类型选择的日志可能不是您想要的。
【解决方案3】:

在 C++0x 中,可以使用以下 lambda 版本:

template<class Iterator>
typename Iterator::value_type Entropy(Iterator begin, Iterator end) {
  typedef typename Iterator::value_type Value;
  return accumulate(begin, end, Value(), 
      [] (Value i, Value j)-> Value { return i - j * log(j); });  
}

【讨论】:

  • 当您不使用任何非局部变量(即开始、结束)时,为什么要使用 [&]?
  • 你说得对@Fred,我承认我在这个区域还有我的 L 板。已编辑,谢谢。更好地理解 lambda 语法的私人探索的一部分。
  • 我认为我们都在追求这个目标,除了 litb 几年前显然掌握了它:)
【解决方案4】:

最好使用std::iterator_traits

typedef typename std::iterator_traits<Iterator>::value_type Value;

这允许 Iterator 成为一个指针。

【讨论】:

    猜你喜欢
    • 2010-10-22
    • 1970-01-01
    • 2016-03-22
    • 2011-03-26
    • 2012-01-13
    • 1970-01-01
    • 1970-01-01
    • 2010-11-11
    • 2011-08-24
    相关资源
    最近更新 更多