понедельник, 3 ноября 2008 г.

Создание итератора-адаптера

Очень часто в коде С++ (и не обязательно производства "до рождества христова") встречается предоставляют доступа к набору каких-либо объектов в следующем виде:
size_t GetItemCount();
value_type GetItem(size_t i);

Для использования стандартными алгоритмами такое представление неудобно, поскольку требует в лобовом варианте предварительного формирования промежуточного контейнера (sic!).
Решение проблемы достаточно простое (с использованием boost):

class smart_iterator : public boost::iterator_facade<std::random_access_iterator_tag, value_type, size_t>
{
public:
iterator(size_t i = 0) : index_(i) { }
// implementation
public:
reference dereference() const { return GetItem(index_); }
void increment() { ++index_; }
void decrement() { --index_; }
bool equal(const iterator& iter) const { return index_ == iter.index_; }

private:
size_t index_;
};


Теперь можно делать STL-подобные вызовы:
std::copy(smart_iterator(), iterator(GetItemCount()), ...);

Очевидно, что для написания итератора boost привлекать не обязательно, но при взгляде на тот объем кода, который нужно вбить, чтобы сделать правильный STL-compliant итератор, желание так делать без причины сильно уменьшается :-)
А поскольку в наших проектах boost используется массово, то никаких новых зависимостей по заголовкам такой прием чаще всего уже не порождает.

Комментариев нет: