Как использовать итераторы `boost :: range` со стандартными итераторами - PullRequest
5 голосов
/ 19 марта 2019

У меня есть функции, которые принимают итераторы std::vector, как в

typedef std::vector<Point> Points;

Points ConvexHull(Points::const_iterator first, Points::const_iterator last);

Я обычно передаю им итераторы std, но иногда мне нужно работать с boost итераторами, такими как boost::join итератор диапазона. Как я должен изменить параметризацию своих функций, в идеале без шаблонов, чтобы они принимали оба итератора? Кроме того, как мне указать в каждом типе, какие концепции итераторов мне нужны?

Я попытался просмотреть документацию boost::range, но это меня смущает, и я не знаю, с чего начать.

Например, я не смог найти разницу между boost::range_details::any_forward_iterator_interface и boost::range_details::any_forward_iterator_wrapper и должен ли я использовать любой из них, чтобы указать, что мне нужен прямой итератор.


Edit:

Если я использую boost::any_range, как я могу передать неконстантные ссылки на lvalue?

Например:

template<typename T>
using Range = boost::any_range<T, boost::random_access_traversal_tag, 
                               T, std::ptrdiff_t>;


f(Range<Point> &points);  // defined elsewhere

// -------------

vector<Point> vec;
f(vec);  // error; cannot bind non-const lvalue reference to unrelated type

Ответы [ 2 ]

4 голосов
/ 19 марта 2019

имеет any_range для этой цели и подходит для обеих целей.

https://www.boost.org/doc/libs/1_60_0/libs/range/doc/html/range/reference/ranges/any_range.html

Из вашего примера это выглядело быкак это:

#include <boost/range/any_range.hpp>

typedef boost::any_range<Point,
                         boost::bidirectional_traversal_tag,
                         Point,
                         std::ptrdiff_t
                        > PointRange;
1 голос
/ 19 марта 2019

Вы должны строго рассмотреть возможность использования шаблона.Это позволит компилятору хранить полезную информацию о том, какие операции на самом деле происходят, что значительно помогает генерировать оптимизированный вывод.Соглашение std:: заключается в названии параметра типа для требуемой концепции.Например,

template< class BidirIt, class UnaryPredicate > // anything bidirectional (which includes random access)
BidirIt std::partition( BidirIt first, BidirIt last, UnaryPredicate p );

Если вы действительно не хотите шаблон, вам все равно не следует называть имя в detail пространстве имен.Что-то вроде

#include <boost/range/any_range.hpp>

using PointRange = boost::any_range<Point, boost::random_access_traversal_tag>; // or another traversal tag.
using PointIterator = PointRange::iterator;

Скорее всего, вам придется проходить PointRange & реже , чем, скажем, int *&.Почти всегда передача по значению является правильным поведением.Копировать дешево, так как он содержит итератор begin и end из Range , из которого он был построен, и ничего более.

...