隐式升级以避免std :: partial_sum中的溢出

时间:2010-02-03 02:36:44

标签: c++ stl overflow

此代码会出现溢出,因为中间结果的类型不依赖于目标类型:

vector< uint8_t > increments;
…
vector< uint32_t > increasing( increments.size() );
partial_sum( increments.begin(), increments.end(), increasing.begin() );

然而,这也是如此(GCC 4.2):

partial_sum( increments.begin(), increments.end(), increasing.begin(),
             plus< uint32_t >() );

plus< uint32_t >不应该提升其操作数并避免溢出?

编辑:我太沉迷于上瘾了。短暂休息后,我坐下来检查实施情况。它这样做:

  /* input_iterator::value_type */ __value = __binary_op(__value, *__first);
  *++__result = __value;

我不认为这是合规的,所以我会查看最新版本,并可能提交错误...我们转到这里:http://gcc.gnu.org/bugzilla/show_bug.cgi?id=42943

1 个答案:

答案 0 :(得分:1)

根据http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#539,自{n3000(最新版)发布以来partial_sum已完全重新定义:

  

效果:让VT成为InputIterator   值类型。对于非空的范围,   初始化类型的累加器acc   带*的第一个VT并执行* result =   ACC。对于每个迭代器我在[first +   1,最后)按顺序,然后是acc   由acc = acc + * i或acc =修改   binary_op(acc,* i)并分配给   *(结果+(我 - 第一))。

  

然后可以是“扩大”行为   通过编写自定义代理获得   迭代器,有点参与。

我真的看不到以这种方式做事的好处。阅读缺陷报告,我认为除了

之外没有任何理由
  

算法的目的是使用。来执行计算   输入迭代器的类型。

Arrrgh。

编辑:我继续实施了一个扩展的输入迭代器。像宣传的那样工作。

template< class Base, class Wider >
struct widen_iter : iterator< input_iterator_tag, Wider > {
    Base b;
    widen_iter( Base const &inb = Base() ) : b( inb ) {}
    Wider operator*() const { return Wider( *b ); }
    Wider const *operator->() const { Wider t( *b ), *ta = &t; return ta; }
    widen_iter &operator++() { ++ b; return *this; }
    widen_iter operator++(int) { widen_iter t = *this; ++ b; return t; }
    bool operator==( widen_iter const &r ) const { return b == r.b; }
    bool operator!=( widen_iter const &r ) const { return b != r.b; }
};
template< class Wider, class Base >
widen_iter< Base, Wider >
widener( Base b ) { return widen_iter< Base, Wider >( b ); }

如果有一个通用的逐个仿函数输入迭代器,那么会更短。