【发布时间】:2021-05-27 11:12:18
【问题描述】:
我想要一个函数来修改传入的已知类型元素,匹配我们在外部循环中迭代的私有数据,将每个元素与传入的元素进行比较。数量很小,因此无需构建地图或优化 n² 的性质。在伪代码中:
function fill_in_thing_data([in-out] things)
for (item in private_items)
info = wrangle(item)
for (thing in things)
if (matching(thing, info))
thing.data = info.data
说 private_items 进行迭代或设置迭代的成本很高,所以我绝对希望在外循环中使用它。
很简单,对吧?除了我想要两个共享一些底层代码的 C++ 重载函数,一个接受对事物的非常量引用,一个接受对事物向量的引用:
void fill_in_thing_data(Thing& single_thing);
void fill_in_thing_data(std::vector<Thing>& some_things);
在这两个函数之间共享代码的最佳方式是什么?我在想一个辅助函数,它接受迭代器或一些类似的序列类型,第一个函数传入一个由 1 个元素组成的迭代器或序列,另一个由向量组成。我想使用 C++ 惯用语,所以想用 ForwardIterators 来做。
问题:
- C++ 迭代器通常并不容易。好的,使用它们没问题,但是编写一个将任何类型的 ForwardIterator 简单地转换为已知类型的函数似乎出乎意料地棘手。
- 对单个元素引用的特殊情况迭代器是否可用?还是很容易定义的东西?似乎答案是否定的。
这是我使用传入的访问者 lambda 和传回的访问 lambda 的丑陋解决方案,而不是迭代器,从而允许从共享函数中抽象出迭代逻辑:
using VisitThing = std::function<bool(Thing& thing)>;
using ThingVisitor = std::function<bool(VisitThing visit)>;
void match_things(ThingVisitor visitor);
void fill_in_thing_data(Thing& single_thing) {
match_things([&](VisitThing visit) {
visit(single_thing);
});
}
void fill_in_thing_data(std::vector<Thing>& some_things) {
match_things([&](VisitThing visit) {
for (auto& thing : some_things) { visit(thing); }
});
}
void match_things(ThingVisitor visitor) {
auto stuff = fetch_private_stuff()
while (item = stuff.get_next_item()) { // can't change this home-brew iteration
auto item_info = wrangle(item) // but more complex, logic about skipping items etc
visitor([&](Thing& thing) {
if (item_info.token == thing.token)) {
thing.data = item_info.data;
}
}
}
}
我错了,可以用迭代器做到这一点而不会太复杂吗?或者我可以通过其他方式更好地做到这一点,比如一个好的数据结构类,它可以使用引用或向量构建,然后将其传入?或者像其他明显的东西我只是没有看到?谢谢!
【问题讨论】: