代码之家  ›  专栏  ›  技术社区  ›  Michael Kristofik

对容器中的所有元素求和成员函数结果的最佳方法是什么?

  •  11
  • Michael Kristofik  · 技术社区  · 14 年前

    假设我有以下对象:

    struct Foo
    {
        int size() { return 2; }
    };
    

    获得总数的最佳方法是什么(最容易维护、可读等) size 中的所有对象 vector<Foo> ?我会发布我的解决方案,但我对更好的想法感兴趣。

    更新:

    到目前为止,我们有:

    • std::累加和一个函数
    • Std::Accumulate和lambda表达式
    • 普通ol'for循环

    还有其他可行的解决方案吗?你能用做些可维护的东西吗 boost::bind std::bind1st/2nd ?

    5 回复  |  直到 8 年前
        1
  •  25
  •   Stack Overflow is garbage    11 年前

    除了你自己的建议,如果你的编译器支持C++ 0x lambda表达式,你可以使用这个较短的版本:

    std::vector<Foo> vf;
    
    // do something to populate vf
    
    
    int totalSize = std::accumulate(vf.begin(),
                                    vf.end(),
                                    0, 
                                    [](int sum, const Foo& elem){ return sum + elem.size();});
    
        2
  •  7
  •   Michael Kristofik    14 年前

    使用 std::accumulate 和函子。

    #include <functional>
    #include <numeric>
    
    struct SumSizes : public std::binary_function<int, Foo, int>
    {
        int operator()(int total, const Foo& elem) const
        {
            return total + elem.size();
        }
    };
    
    std::vector<Foo> vf;
    
    // do something to populate vf
    
    int totalSize = std::accumulate(vf.begin(),
                                    vf.end(),
                                    0, 
                                    SumSizes());
    
        3
  •  7
  •   rafak    14 年前

    我发现boost迭代器elegants,尽管它们可能有点冗长(基于范围的算法会使这更好)。在这种情况下 transform iterators 可以做这项工作:

    #include <boost/iterator/transform_iterator.hpp>
    //...
    
    int totalSize = std::accumulate(
        boost::make_transform_iterator(vf.begin(), std::mem_fn(&Foo::size)),
        boost::make_transform_iterator(vf.end(), std::mem_fn(&Foo::size)),0);
    

    编辑:替换“ boost::bind(&Foo::size,_1) “由” std::mem_fn(&Foo::size)

    编辑:我刚发现Boost.Range库已经更新,引入了Range算法!以下是同一解决方案的新版本:

    #include <boost/range/distance.hpp> // numeric.hpp needs it (a bug?)
    #include <boost/range/numeric.hpp> // accumulate
    #include <boost/range/adaptor/transformed.hpp> // transformed
    //...
    int totalSize = boost::accumulate(
        vf | boost::adaptors::transformed(std::mem_fn(Foo::size)), 0);
    

    注:性能大致相同(见我的评论):内部, transformed 使用 transorm_iterator .

        4
  •  6
  •   Michael Miller    8 年前

    使用C++ 11(和超出)基于循环的范围

    std::vector<Foo> vFoo;
    // populate vFoo with some values...
    int totalSize = 0;
    for (const auto& element: vFoo) {
        totalSize += element.size();
    }
    
        5
  •  4
  •   Philipp    14 年前

    下面是实际解决方案:

    typedef std::vector<Foo> FooVector;
    FooVector vf;
    int totalSize = 0;
    for (FooVector::const_iterator it = vf.begin(); it != vf.end(); ++it) {
      totalSize += it->size();
    }