汇总多个捐助者的捐款

发布于 2024-07-19 08:27:31 字数 1079 浏览 6 评论 0原文

当我尝试现代化我的 C++ 技能时,我不断遇到“STL 方式”对我来说并不明显的情况。

我有一个对象想要将多个来源的贡献收集到一个容器中(通常是一个 std::vector )。 每个源都是一个对象,每个对象都提供一个方法 get_contributions(),该方法返回任意数量的贡献(从 0 到多个)。 收集器将对每个贡献者调用 get_contributions() 并将结果聚合到单个集合中。

问题是,get_contributions() 的最佳签名是什么?

选项 1:std::vectorget_contributions() const

这是最简单的,但它会导致大量复制,因为收集器将每组结果复制到主集合中。 是的,性能在这里很重要。 例如,如果贡献者是几何模型,并且获得贡献相当于将它们镶嵌成三角形进行渲染,那么速度就很重要,而且贡献的数量可能会很大。

选项 2:模板 <类型名称容器> void get_contributions(container &target) const

这允许每个贡献者通过调用 target.push_back(foo) 将其贡献直接添加到主容器。 这里的缺点是我们将容器暴露给其他类型的检查和操作。 我宁愿保持界面尽可能窄。

选项 3:templatevoid get_contributions(out_it &it) const

在此解决方案中,聚合器将为主集合传递一个 std::back_insert_iterator,而各个贡献者将执行 *it++ = foo; 对于每个贡献。 这是迄今为止我想到的最好的方法,但我感觉必须有一种更优雅的方法。 back_insert_iterator 感觉就像是一个拼凑的东西。

选项 3 是最好的还是有更好的方法? 这种聚集模式有名字吗?

As I try to modernize my C++ skills, I keep encountering this situation where "the STL way" isn't obvious to me.

I have an object that wants to gather contributions from multiple sources into a container (typically a std::vector). Each source is an object, and each of those objects provides a method get_contributions() that returns any number of contributions (from 0 to many). The gatherer will call get_contributions() on each contributor and aggregate the results into a single collection.

The question is, what's the best signature for get_contributions()?

Option 1: std::vector<contribution> get_contributions() const

This is the most straightforward, but it leads to lots of copying as the gatherer copies each set of results into the master collection. And yes, performance matters here. For example, if the contributors were geometric models and getting contributions amounted to tesselating them into triangles for rendering, then speed would count and the number of contributions could be enormous.

Option 2: template <typename container> void get_contributions(container &target) const

This allows each contributor to add its contributions directly to the master container by calling target.push_back(foo). The drawback here is that we're exposing the container to other types of inspection and manipulation. I'd prefer to keep the interface as narrow as possible.

Option 3: template <typename out_it> void get_contributions(out_it &it) const

In this solution, the aggregator would pass a std::back_insert_iterator for the master collection, and the individual contributors would do *it++ = foo; for each contribution. This is the best I've come up with so far, but I'm left with the feeling that there must be a more elegant way. The back_insert_iterator feels like a kludge.

Is Option 3 the best, or is there a better approach? Does this gathering pattern have a name?

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

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

发布评论

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

评论(3

心房的律动 2024-07-26 08:27:31

还有第四种,需要您定义迭代器范围。 查看 Alexandrescu 的演讲 “迭代器必须消失”

There's a fourth, that would require you to define you iterator ranges. Check out Alexandrescu's presentation on "Iterators must go".

意中人 2024-07-26 08:27:31

选项3是最惯用的方式。 请注意,您不必使用 back_insert_iterator。 如果您知道要添加多少个元素,则可以调整向量的大小,然后提供常规向量迭代器。 然后它不会调用push_back(并且可能会为您节省一些复制)

back_insert_iterator的主要优点是它可以根据需要扩展向量。

但这并不是一个拼凑。 它就是为了这个目的而设计的。

一项小的调整是按值传递迭代器,然后在函数返回时返回它。

Option 3 is the most idiomatic way. Note that you don't have to use back_insert_iterator. If you know how many elements are going to be added, you can resize the vector, and then provide a regular vector iterator instead. It won't call push_back then (and potentially save you some copying)

back_insert_iterator's main advantage is that it expands the vector as needed.

It's not a kludge though. It's designed for this exact purpose.

One minor adjustment would be to take pass the iterator by value, and then return it when the function returns.

用心笑 2024-07-26 08:27:31

我想说有两种惯用的 STL 方法:选项 3(顺便说一下,采用一个输出迭代器,您可以按值传递该迭代器)和采用一个函子,您可以通过每个贡献来调用该函子。

当然,这些中的每一个仅当适合将 get_contributions 实现为模板时才合适。

I would say there are two idiomatic STL ways: your Option 3 (taking an output iterator, which you'd pass by value, by the way) and taking a functor which you would call with each of the contributions.

Each of these is only appropriate if it is suitable to implement get_contributions as a template, of course.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文