假设我有以下对象:
struct Foo
{
int size() { return 2; }
};
获得size
中所有对象的总vector<Foo>
的最佳方法(最易维护,可读等)是什么?我会发布我的解决方案,但我对更好的想法感兴趣。
更新
到目前为止,我们已经:
还有其他可行的解决方案吗?您可以使用boost::bind
或std::bind1st/2nd
来维护某些内容吗?
答案 0 :(得分:25)
除了你自己的建议,如果你的编译器支持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();});
答案 1 :(得分:7)
使用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());
答案 2 :(得分:7)
我找到了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库已经更新,引入了范围算法!这是同一解决方案的新版本:
#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
。
答案 3 :(得分:6)
使用C ++ 11(及更高版本)基于范围的for循环
std::vector<Foo> vFoo;
// populate vFoo with some values...
int totalSize = 0;
for (const auto& element: vFoo) {
totalSize += element.size();
}
答案 4 :(得分:4)
这是脚踏实地的解决方案:
typedef std::vector<Foo> FooVector;
FooVector vf;
int totalSize = 0;
for (FooVector::const_iterator it = vf.begin(); it != vf.end(); ++it) {
totalSize += it->size();
}