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

发布于 2024-09-09 07:22:01 字数 445 浏览 14 评论 0原文

假设我有以下对象:

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

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

更新:

到目前为止,我们有:

  • std::accumulate 和函子
  • std::accumulate 和 lambda 表达式
  • 普通 ol' for 循环

还有其他可行的解决方案吗?您可以使用 boost::bindstd::bind1st/2nd 使某些内容可维护吗?

Let's say I have the following object:

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

What's the best way (most maintainable, readable, etc.) to get the total size of all objects in a vector<Foo>? I'll post my solution but I'm interested in better ideas.

Update:

So far we have:

  • std::accumulate and a functor
  • std::accumulate and a lambda expression
  • plain ol' for-loop

Are there any other workable solutions? Can you make something maintainable using boost::bind or std::bind1st/2nd?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

兰花执着 2024-09-16 07:22:01

除了您自己的建议之外,如果您的编译器支持 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();});

In addition to your own suggestion, if your compiler supports C++0x lambda expressions, you can use this shorter version:

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();});
Smile简单爱 2024-09-16 07:22:01

使用 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());

Use std::accumulate and a functor.

#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());
梦醒灬来后我 2024-09-16 07:22:01

我发现 Boost 迭代器很优雅,尽管它们可能有点冗长(基于范围的算法会让这更好)。在这种情况下 转换迭代器 可以执行以下操作:作业:

#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

I find Boost iterators elegants, although they can be a bit verbose (range-based algorithms would make this better). In this case transform iterators can do the job:

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

Edit: replaced "boost::bind(&Foo::size,_1)" by "std::mem_fn(&Foo::size)"

Edit: I just found that the Boost.Range library has been updated to introduce range algorithms! Here is a new version of the same solution:

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

Note: the performances are approximately the same (see my comment): internally, transformed uses transorm_iterator.

﹎☆浅夏丿初晴 2024-09-16 07:22:01

使用 C++11(及更高版本)基于范围的 for 循环

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

using C++11 (and beyond) range-based for loop

std::vector<Foo> vFoo;
// populate vFoo with some values...
int totalSize = 0;
for (const auto& element: vFoo) {
    totalSize += element.size();
}
少年亿悲伤 2024-09-16 07:22:01

这是实际的解决方案:

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

Here is the down-to-earth solution:

typedef std::vector<Foo> FooVector;
FooVector vf;
int totalSize = 0;
for (FooVector::const_iterator it = vf.begin(); it != vf.end(); ++it) {
  totalSize += it->size();
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文