代码之家  ›  专栏  ›  技术社区  ›  Potatoswatter

隐式提升以避免std::分部和溢出

  •  2
  • Potatoswatter  · 技术社区  · 15 年前

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

    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;
    

    我不认为这是符合的,所以我会检查最新版本,也许会提交一个bug,然后我们开始: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=42943

    1 回复  |  直到 15 年前
        1
  •  1
  •   Potatoswatter    15 年前

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

    效果:让VT成为输入者 值类型。对于非空范围, 初始化类型为的Accumulator 带*第一个并执行*结果的VT= 在[第一个+ 1,最后一个)依次,然后是acc 由acc=acc+*i或acc修改= 二进制_op(acc,*i),并分配给 *(结果+(i-第一个))。

    “扩大”行为可以是 通过编写自定义代理获取 迭代器,有点复杂。

    我真的看不出这样做的好处。阅读缺陷报告,我看不出任何理由

    算法的目的是使用 输入迭代器的类型。

    阿拉尔

    编辑: 我接着实现了一个扩展输入迭代器。如广告所示。

    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 ); }
    

    如果有一个按函数输入迭代器的通用过滤器,则会短得多。