2011-10-06 34 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