2011-10-06 120 views
2

我有一堆类实现基于顶点的几何对象,如TriangleMesh,PointClouds或Edgesets。它们都从VertexBasedGeometry继承。我现在希望它们都返回一个双向迭代器对其顶点的引用。这将允许以非模板方式访问任何VertexBasedGeometry的顶点。现在,我对迭代器不太熟悉,事实证明这很困难。我尝试如下所示:所有双向迭代器的常见类类型C++

class VertexBasedGeometry : public Geometry 
{ 
public: 

typedef std::iterator<std::bidirectional_iterator_tag,defines::Vector3 > VertexIterator; 

VertexBasedGeometry(){}; 

virtual VertexIterator begin()=0; 
virtual VertexIterator end()=0; 
}; 

在TraingleMesh,从VertexBasedGeometry继承我现在尝试实现该功能首先返回其中包含了顶点的std ::向量的开始迭代器。这将导致以下编译器错误的GCC 4.2(苹果):现在

Mesh.cpp:25: error: conversion from '__gnu_cxx::__normal_iterator<defines::Vector<double, 3>*, std::vector<defines::Vector<double, 3>, std::allocator<defines::Vector<double, 3> > > >' to non-scalar type 'std::iterator<std::bidirectional_iterator_tag, defines::Vector<double, 3>, long int, defines::Vector<double, 3>*, defines::Vector<double, 3>&>' requested 

我的问题是:为什么这个不行,我应该怎么改变这种得到它的工作? 阅读关于迭代器的更多信息,我有一种轻微的感觉,我无法找到任何双向迭代器的通用类型,是吗?有些类可能会将其顶点存储在std :: vector之外的其他容器中,其他类已经提供了(非stl符合)迭代器,这些迭代器我想适应我的常见类型。我愿意接受任何有关如何实施的建议。

回答

2

std :: iterator只是一个你从中派生出来的标签类,你的迭代器的类型必须在编译时被知道到实现类中。如果你想从迭代代码中隐藏迭代器实现,你必须添加一个间接级别,例如Thomas Becker's any_iterator

+0

我现在就试试看。首先必须阅读any_pointer。谢谢,@thiton –

1

迭代器只是一个松散的概念,与现实生活中的迭代器类在任何意义上都没有关系。一般来说,你不会为你的类写一个完整的迭代器类。

迭代器确实共享某些共同点,并且您必须设计它们以便可以用std::iterator_traits来探测它们。这意味着任何给定的迭代器实现都会有很多类似的代码(类似于Boost的iterator facade可能会有所帮助)。尽管如此,你的类的接口(如begin(),end()find())将不得不返回自己的迭代器类型,并且必须编写迭代器的实现(即增量和取消引用操作符)。

+0

我想这是推理它的正确方法,而any_iterator提供了一个实用的解决方法,直到我做得很好。谢谢 –

0

BidirectionalIterator不是一个类,它是一个概念。一个概念由一组具有指定语义的需求和表达式组成。如果一个类满足一个概念的所有要求,它就被认为是这个概念的一个模型。这意味着对于某些概念的迭代器没有共同的类,因为stdlib不能基于子类型多态性工作,而是基于概念。

那么什么是std::iterator?它可以帮助您轻松定义特定迭代器的特征,但不提供功能。它只支持编译时间元编程。

有几个工具可以帮助您实现自己的类,这些类为Boost.Iterators这样的特定迭代器建模。

+0

谢谢。整个混淆实际上始于没有意识到面向对象和泛型编程之间的区别。我想这些概念只是有点兼容。 –

+0

@oggologgo是的,它们有点正交。我推荐Stepanov的“编程元素”作为对泛型编程和负载Boost代码的非常全面的介绍,以便在工作中看到它。 – pmr