C ++中带有lambda的简单自定义迭代器 [英] Simple customized iterator with lambdas in C++

查看:57
本文介绍了C ++中带有lambda的简单自定义迭代器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

  template< typename InputIterator>double compute_area(InputIterator首先,InputIterator以后){//做东西}template< typename InputIterator,typename OutputIterator>无效//做东西}结构场景{std :: vector< Point>顶点foo(const std :: vector< int>& polygon){//用有限的mumbo-jumbo创建一个简单的包装器自动函子= [](int i)->点与点{return vertices [polygon [i]];});MagicIterator polyBegin(0,functor);MagicIterator polyEnd(polygon.size(),functor);//注意:我希望它们充当随机访问迭代器//然后直接使用double a = compute_area(polyBegin,polyEnd);//奖金:创建类似于std :: back_inserter的自定义插入器std :: vector< int>结果;凸包(polyBegin,polyEnd,MagicInserter(result));}}; 

因此,正如您所看到的,我正在寻找一些通用的东西.我还考虑过使用lambda,但是在如何继续保持它简单和用户友好方面我有些困惑.

解决方案

我建议 Boost的变换迭代器.这是一个示例用法:

  #include< boost/iterator/transform_iterator.hpp>#include< vector>#include< cassert>#include< functional>结构点{int x,y;};template< typename It>无效计算(开始,结束){while(开始!=结束){begin-> x = 42;begin-> y = 42;++开始;}}int main(){std :: vector< Point>顶点(5);std :: vector< int>多边形{2,3,4};std :: function< Point&(int)>函子= [&](int i)->点与点{返回顶点[i];};自动polyBegin = boost :: make_transform_iterator(polygon.begin(),functor);自动polyEnd = boost :: make_transform_iterator(polygon.end(),functor);计算(polyBegin,polyEnd);assert(vertices [2] .y == 42);} 

我不太了解有关自定义 back_inserter 的内容.如果存储在 result 向量中的类型与仿函数返回的类型相同,则标准库中的那个将起作用.否则,您也可以将其包装在 transform_iterator 中.

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

Suppose I have a container which contains int, a function that works over containers containing Point, and that I have a function that given some int gives me the corresponding Point it represents (imagine that I have indexed all the points in my scene in some big std::vector<Point>). How do I create a simple (and efficient) wrapper to use my first container without copying its content?

The code I want to type is something like that:

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

So, as you've seen, I'm looking for something a bit generic. I thought about using lambdas as well, but I'm getting a bit mixed up on how to proceed to keep it simple and user-friendly.

解决方案

I suggest Boost's Transform Iterator. Here's an example usage:

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

I didn't quite get the part about custom back_inserter. If the type stored in result vector is the same as what the functor returns, the one from standard library will do. Otherwise you can just wrap it in transform_iterator, too.

Note that the functor is stored in a std::function. Boost relies on the functor to have a typedef result_type defined and lambdas don't have it.

这篇关于C ++中带有lambda的简单自定义迭代器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆