【问题标题】:Is there an STL adaptor on iterator invoking callback for each collection element?迭代器上是否有 STL 适配器为每个集合元素调用回调?
【发布时间】:2016-09-25 09:36:46
【问题描述】:

我对以下用例的适配器特别感兴趣:

std::list<int> input {1, 2, 3};
std::list<int> result;
auto l = [](auto e) { return e + 1; };
result.insert(result.end(), adaptor(input.begin(), l), adaptor(input.end(), l));
// now result == {2, 3, 4}

如果适配器不使用外部库(例如 boost),那就太好了。

【问题讨论】:

  • 喜欢带有后插入器的std::transform
  • @PiotrSkotnicki 我想这正是我想要的……谢谢!!

标签: c++ stl c++14


【解决方案1】:

您的问题被标记为 C++14,并说没有外部库依赖会很好(很公平)。

不过,为了将来的参考,请注意range 库似乎正朝着被标准库(C++17 range for loop is already compliant with one of its major points)采用的方向发展。因此,使用range,代码可能如下所示:

#include <list>
#include <range/v3/all.hpp>

int main() {
    const std::list<int> input{1, 2, 3};
    const std::list<int> result = 
        input | ranges::view::transform([](int i){ return i + 1; });
}

这就是未来标准库 C++ 代码可能的样子。无论如何,它都有它的优点:

  • 它看起来更直观(尽管这可能是主观的)。

  • 注意如何制作result const

【讨论】:

  • 通常我对外部库开放,但我坚持的项目需要尽可能轻松......你的方法非常简单,如果我不受限制,我肯定会选择您的答案中的代码
【解决方案2】:

所以使用 PiotrSkotnicki 的建议,我最终得到了这样的代码:

#include <algorithm>
#include <iterator>
#include <list>

int main() {
   std::list<int> input {1, 2, 3};
   std::list<int> output;
   std::transform(input.begin(), input.end(), std::back_inserter(output), [](auto e){ return e + 1;});
}

【讨论】:

  • 你可以使用std::transform(input.begin(), input.end(), std::back_inserter(result), [](auto e){ return e + 1;});,它会自动添加元素而不需要resize
  • 您应该在调用转换之前添加对output.reserve(input.size()) 的调用。
  • @Shloim 不幸的是,我认为列表没有向量::reserve 等价物,但如果有它肯定会提高效率......
  • 我的错误。以为我们在处理向量。
猜你喜欢
  • 2022-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多