C++ 中带有 lambda 的简单自定义迭代器

sku*_*uld 5 c++ lambda containers iterator

假设我有一个包含 的容器int,一个对包含 的容器起作用的函数Point,并且我有一个函数,给定一些int给我Point它所代表的对应值(想象一下我已经在某个大的 中索引了场景中的所有点std::vector<Point>)。如何创建一个简单(且高效)的包装器来使用我的第一个容器而不复制其内容?

我想要输入的代码是这样的:

template<typename InputIterator>
double compute_area(InputIterator first, InputIterator beyond) {
    // Do stuff
}

template<typename InputIterator, typename OutputIterator>
void convex_hull(InputIterator first, InputIterator beyond, OutputIterator result) {
    // Do stuff
}

struct Scene {
    std::vector<Point> vertices;

    foo(const std::vector<int> &polygon) {
        // Create a simple wraper with limited amount of mumbo-jumbo
        auto functor = [](int i) -> Point& { return vertices[polygon[i]]; });
        MagicIterator polyBegin(0, functor);
        MagicIterator polyEnd(polygon.size(), functor);
        // NOTE: I want them to act as random access iterator

        // And then use it directly
        double a = compute_area(polyBegin, polyEnd);

        // Bonus: create custom inserter similar to std::back_inserter
        std::vector<int> result;
        convex_hull(polyBegin, polyEnd, MagicInserter(result));
    }
};
Run Code Online (Sandbox Code Playgroud)

所以,正如你所看到的,我正在寻找一些通用的东西。我也考虑过使用 lambda,但我对如何继续保持简单和用户友好感到有点困惑。

jro*_*rok 3

我建议使用Boost 的 Transform Iterator。这是一个用法示例:

#include <boost/iterator/transform_iterator.hpp>
#include <vector>
#include <cassert>
#include <functional>

struct Point { int x, y; };

template<typename It>
void compute(It begin, It end)
{
    while (begin != end) {
        begin->x = 42;
        begin->y = 42;
        ++begin;
    }
}

int main()
{
    std::vector<Point> vertices(5);
    std::vector<int> polygon { 2, 3, 4 };

    std::function<Point&(int)> functor = [&](int i) -> Point& { return vertices[i]; };

    auto polyBegin = boost::make_transform_iterator(polygon.begin(), functor);
    auto polyEnd = boost::make_transform_iterator(polygon.end(), functor);

    compute(polyBegin, polyEnd);
    assert(vertices[2].y == 42);
}
Run Code Online (Sandbox Code Playgroud)

我不太明白有关定制的部分back_inserter。如果向量中存储的类型result与函子返回的类型相同,则使用标准库中的类型。否则你也可以把它包裹起来transform_iterator

请注意,函子存储在std::function. Boost 依赖函子来result_type定义 typedef,而 lambda 则没有。