为write-to-pointer API创建一个行为良好的迭代器 [英] Create a well-behaved iterator for a write-to-pointer API

查看:132
本文介绍了为write-to-pointer API创建一个行为良好的迭代器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我必须为API创建一个迭代器,它只具有旧式的写出指针访问器。有问题的API是OGR;其中一个类是 OGRLineString (供参考: http://www.gdal.org/classOGRLineString.html )。此类存储了许多点,可以使用以下getter方法访问:

I have to create an iterator for an API that features old-style "write-out to pointer" accessors only. The API in question is OGR's; one of the classes in question is OGRLineString (For reference: http://www.gdal.org/classOGRLineString.html). This class stores a number of points, which can be accessed using the following getter method:

 void OGRLineString::getPoint(int pos, OGRPoint *out)

为了使用访问者,我们创建一个新的 OGRPoint 对象并将指针传递给方法,该方法将数据写入分配的对象。例如:

In order to use the accessor one creates a new OGRPoint object and passes the pointer to it to the method, which writes the data to the allocated object. For example:

OGRPoint *p = new OGRPoint();
lineString->getPoint(0, p);

现在,我想实现一个(类似STL的)迭代器。即使我在任何地方都放置了大的警告标志,说明提供的 OGRPoint 是不可修改的(即 const ),并且如果另一段代码修改正在迭代的 OGRLineString ,则不会更新,我得到了内存泄漏问题 OGRPoint const& operator * ()const ,因为API要求我传递一个自定义分配的 OGRPoint 实例,但迭代器必须分配一个。另外,删除迭代器本身时,不应删除迭代器返回的 OGRPoint 。此外, OGRLineString 不会存储为 getPoint <复制的 OGRPoint 的实际实例/ code>,但存储x / y / z坐标的简单结构;所有需要的附加信息(例如,空间参考)都被复制到存取器中。因此,一个简单的 #define私有公共黑客无济于事。

Now, I'd like to implement a (STL-like) iterator. Even if I place big warning signs everywhere stating that the supplied OGRPoints are non-modifiable (i.e., const), and won't update if another piece of code modifies the OGRLineString that is being iterated, I get a memory leak problem with OGRPoint const &operator*() const, because the API requires me to pass a custom-allocated OGRPoint instance, but the iterator would have to allocate one. Plus, the OGRPoints returned by the iterator shouldn't be deleted when the iterator itself is deleted. Additionally, the OGRLineString does not store actual instances of OGRPoint that are being copied for getPoint, but simple structs storing x/y/z coordinates; all required additional information (e.g., the spatial reference) is copied in the accessor. Thus, a simple #define private public hack wouldn't help.

是否有任何理智/干净的方式添加迭代器而不修改 OGRLineString 的原始来源?例如,有没有办法向原始类添加功能,或修改它,就像Ruby的猴子修补功能一样?或者观察容器的生命周期,以便清理迭代器返回的 OGRPoint 实例?

Is there any sane/clean way to add an iterator without modifying the original source of OGRLineString? E.g., is there a way to add features to the original class, or modify it, like Ruby's "monkey patching" feature would do? Or watch the container's life time in order to clean up on the OGRPoint instances returned by the iterator?

推荐答案

这假定OGRPoint是可复制构造的。如果没有,请使用智能指针。

This assumes that OGRPoint is copy-constructible. If not, use smart-pointers.

#include <iterator>

#include <ogr_geometry.h>

struct OGR_SimpleCurve_Points_Iterator : std::iterator< std::random_access_iterator_tag, const OGRPoint >
{
    OGR_SimpleCurve_Points_Iterator( OGRSimpleCurve* curve=nullptr, int index=0 )
        : curve(curve), index(index) {}

    OGR_SimpleCurve_Points_Iterator& operator++() { ++index; return *this; }
    OGR_SimpleCurve_Points_Iterator operator++(int) { OGR_SimpleCurve_Points_Iterator ret(*this); ++index; return ret; }
    OGR_SimpleCurve_Points_Iterator& operator--() { --index; return *this; }
    OGR_SimpleCurve_Points_Iterator operator--(int) { OGR_SimpleCurve_Points_Iterator ret(*this); --index; return ret; }

    OGR_SimpleCurve_Points_Iterator& operator+=(int n) { index+=n; return *this; }
    OGR_SimpleCurve_Points_Iterator& operator-=(int n) { index-=n; return *this; }

    OGR_SimpleCurve_Points_Iterator operator+(int n) { return OGR_SimpleCurve_Points_Iterator{curve,index+n}; }
    OGR_SimpleCurve_Points_Iterator operator-(int n) { return OGR_SimpleCurve_Points_Iterator{curve,index-n}; }

    int operator-(const OGR_SimpleCurve_Points_Iterator& other) { return index-other.index; }

    OGRPoint operator*() { OGRPoint p; curve->getPoint(index,&p); return p; }

    OGRPoint operator[](int ofs) { OGRPoint p; curve->getPoint(index+ofs,&p); return p; }

    bool operator == ( const OGR_SimpleCurve_Points_Iterator& other ) { return index==other.index; }
    bool operator != ( const OGR_SimpleCurve_Points_Iterator& other ) { return index!=other.index; }
    bool operator  > ( const OGR_SimpleCurve_Points_Iterator& other ) { return index >other.index; }
    bool operator >= ( const OGR_SimpleCurve_Points_Iterator& other ) { return index>=other.index; }
    bool operator  < ( const OGR_SimpleCurve_Points_Iterator& other ) { return index <other.index; }
    bool operator <= ( const OGR_SimpleCurve_Points_Iterator& other ) { return index<=other.index; }

private:
    OGRSimpleCurve* curve;
    int index;
};

OGR_SimpleCurve_Points_Iterator begin( OGRSimpleCurve* curve )
{
    return OGR_SimpleCurve_Points_Iterator{curve};
}

OGR_SimpleCurve_Points_Iterator end( OGRSimpleCurve* curve )
{
    return OGR_SimpleCurve_Points_Iterator{curve,curve->getNumPoints()};
}

这篇关于为write-to-pointer API创建一个行为良好的迭代器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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