#c #stl #iterator #boost-iterators
#c #stl #итератор #boost-итераторы
Вопрос:
У меня есть куча классов, которые реализуют геометрические объекты на основе вершин, такие как TriangleMesh, PointClouds или наборы ребер. Все они наследуются от 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, возвращая итератор 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>amp;>' requested
Теперь мой вопрос: почему это не работает, и как я должен изменить это, чтобы заставить его работать?
Читая больше об итераторах, у меня возникло легкое ощущение, что я не смогу найти общий тип для любого двунаправленного итератора, верно? Некоторые из классов могут иметь свои вершины, хранящиеся в контейнерах, отличных от std::vector, другие уже предоставляют (не соответствующие stl) итераторы, которые я хочу адаптировать к моему общему типу. Я открыт для любых рекомендаций, как это реализовать.
Ответ №1:
std::iterator — это всего лишь класс тегов, который вы производите от него, и тип вашего итератора должен быть известен реализующему классу во время компиляции. Если вы хотите скрыть реализацию итератора от итерационного кода, вы должны добавить уровень косвенности, например, any_iterator Томаса Беккера.
Комментарии:
1. Я попробую прямо сейчас. Сначала нужно прочитать о any_pointer . Спасибо, @thiton
Ответ №2:
Итераторы — это всего лишь расплывчатая концепция, и классы итераторов в реальной жизни никак не связаны. В общем, вам не удастся написать полный класс итератора для вашего класса.
Итераторы имеют определенные общие черты, и вы должны спроектировать их так, чтобы их можно было исследовать std::iterator_traits
. Это означает, что любая реализация данного итератора будет иметь много похожего кода (и может помочь что-то вроде фасада итератора Boost). Тем не менее, интерфейс вашего класса (например begin()
, end()
и find()
) должен будет возвращать ваш собственный тип итератора, и вам придется написать реализацию итератора (т. Е. Операторы увеличения и разыменования).
Комментарии:
1. Я думаю, это правильный способ рассуждать об этом, в то время как any_iterator предоставляет практическое решение, пока я не сделаю это правильно. Спасибо
Ответ №3:
BidirectionalIterator
это не класс, это концепция. Концепция состоит из набора требований и выражений с заданной семантикой. Если класс удовлетворяет всем требованиям концепции, он считается моделью этой концепции. Это означает, что не существует общего класса для итераторов некоторой концепции, поскольку stdlib работает не на основе полиморфизма подтипов, а на основе концепций.
Так что же std::iterator
это такое? Это помощник для упрощения определения характеристик конкретного итератора, но он не предоставляет функциональности. Он позволяет выполнять метапрограммирование только во время компиляции.
Существует несколько инструментов, которые помогут вам реализовать ваши собственные классы, моделирующие конкретный итератор, такой как Boost .Итераторы.
Комментарии:
1. Спасибо. Вся путаница действительно началась с непонимания разницы между OO и универсальным программированием. Я предполагаю, что эти концепции лишь отчасти совместимы.
2. @oggologgo Да, они несколько ортогональны. Я бы рекомендовал «Элементы программирования» Степанова как очень подробное введение в общее программирование и множество повышающего кода, чтобы увидеть его в работе.