Общий тип класса для всех двунаправленных итераторов, c ++ - PullRequest
2 голосов
/ 06 октября 2011

У меня есть несколько классов, которые реализуют геометрические объекты на основе вершин, такие как TriangleMesh, PointClouds или Edgesets.Все они наследуются от VertexBasedGeometry.Теперь я хочу, чтобы все они возвращали двунаправленный итератор по ссылкам его вершин.Это позволило бы получить доступ к вершинам любой VertexBasedGeometry не по шаблону.Теперь, когда я не очень хорошо знаком с итераторами, это оказывается довольно сложно.Моя попытка выглядит следующим образом:

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, я сейчас пытаюсь реализовать функцию begin, возвращая итератор начала std :: vector, который содержит его вершины.Это приводит к следующей ошибке компилятора на gcc 4.2 (apple):

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), которые я хочу адаптировать к своему общему типу.Я открыт для любых рекомендаций, как это реализовать.

Ответы [ 3 ]

2 голосов
/ 06 октября 2011

std :: iterator - это только класс тегов, из которого вы производите, и тип вашего итератора должен быть известен во время компиляции реализующему классу. Если вы хотите скрыть реализацию итератора от кода итерации, вы должны добавить уровень косвенности, например, Томас Беккер any_iterator .

1 голос
/ 06 октября 2011

Итераторы - это всего лишь слабая концепция, и реальные классы итераторов ни в каком смысле не связаны. В общем, вы не можете написать полный класс итератора для вашего класса.

Итераторы имеют некоторые общие черты, и вы должны их спроектировать, чтобы они могли быть проверены с помощью std::iterator_traits. Это означает, что любая данная реализация итератора будет иметь много похожего кода (и может помочь что-то вроде фасадного итератора Boost ). Тем не менее, интерфейс вашего класса (например, begin(), end() и find()) должен будет возвращать ваш собственный тип итератора, а вы должны написать реализацию итератора (т.е. операторы приращения и разыменования).

0 голосов
/ 06 октября 2011

BidirectionalIterator это не класс, это понятие.Концепция состоит из набора требований и выражений с заданной семантикой.Если класс удовлетворяет всем требованиям концепции, он считается моделью этой концепции.Это означает, что не существует общего класса для итераторов некоторой концепции, поскольку stdlib работает не на основе полиморфизма подтипа, а на концепциях.

Так что же такое std::iterator?Это помощник для облегчения определения характеристик конкретного итератора, но он не предоставляет функциональности.Он включает только метапрограммирование времени компиляции.

Есть несколько инструментов, которые помогут вам реализовать ваши собственные классы, которые моделируют определенный итератор, такой как Boost.Iterators .

...