template <class Range> void process_range(Range const &);Вот разбить диапазон на части - пожалуйста, перемещать значения в случайном порядке - да не вопрос, а вот склеить - нифига.
std::vector<foo> v = ...;
std::list<foo> l = ...;
process_range(concat(v, l));
Можно, конечно, создать вектор из ссылок на
foo
, заполнить его ссылками на обекты из первого и второго диапазона, но как-то не спортивно: во-первых само выделение динамической памяти для вектора - не слишком быстрая операция, плюс потом еще ссылки туда копировать. Пришлось написать свой велосипед.С использованием
boost::variant
все получилось достаточно компактно, хотя не максимально эффективно:template <class TIterator1, class TIterator2, ...>
class ConcatIterator : public boost::iterator_facade<...>
{
public:
reference dereference() const
{
return boost::apply_visitor(DereferenceVisitor<reference>(), It);
}
void increment()
{
boost::apply_visitor(IncrementVisitor(), It);
StabilizeForward();
}
void decrement()
{
StabilizeBackward();
boost::apply_visitor(DecrementVisitor(), It);
}
bool equal(const ConcatIterator& lhs) const
{
return (Range == lhs.Range) && (It == lhs.It);
}
private:
size_t Range; // 0 for the first range, 1 for the second range
boost::variant<TIterator1, TIterator2> It, End1, Begin2;
};
PS. Нет худа без добра. Мой велосипед вдохновил разработчиков Boost.Range добавить объединение диапазонов в RangeEx.
Комментариев нет:
Отправить комментарий