Функтор C ++ для вывода адаптера итератора - PullRequest
7 голосов
/ 08 февраля 2010

Данный функтор подходит для использования с std::for_each и друзьями:

template <typename T> struct Foo {
    void operator()(T const& t) { ... }
};

std::for_each(v.begin(), v.end(), Foo<Bar>());

Есть ли какой-нибудь стандартный способ преобразовать это в выходной итератор, подходящий для использования с std::copy и друзьями? (или противоположная адаптация) Что-то вроде:

std::copy(v.begin(), v.end(), functor_output_iterator(Foo<Bar>()));

Который будет вызывать функтор каждый раз, когда значение присваивается итератору:

adapter(F f) : functor(f) { }
adapter& operator*()  { return *this; }
operator=(T const& t) { functor(t); }
operator++()          { }
...

Или, альтернативно:

std::for_each(..., some_adapter(std::ostream_iterator(std::cout)));

Справка:

У меня есть класс, который предоставляет коллекцию, используя выходной итератор:

template <typename It> GetItems(It out) {
    MutexGuard guard(mutex);
    std::copy(items.begin(), items.end(), out);
}

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

например, чтобы получить только уникальные предметы:

std::set<whatever> set;
obj->GetItems(std::inserter(set, set.end()));

Это чертовски бьет из:

ObjLock lock = obj->GetLock();
for (int i = 0; i < obj->GetItemCount(); ++i) {
    Item* item = obj->GetItem(i);
    ...

Теперь я также хочу иметь возможность объединять эти элементы, а не копировать их. (См. этот вопрос ). Где я обычно делаю что-то вроде:

std::for_each(v.begin(), v.end(), Joiner<Foo>());

Теперь я мог бы создать два отдельных метода для одних и тех же элементов данных, один из которых вызывает std::copy, а другой - std::for_each, но было бы неплохо иметь возможность определить только один такой метод, используя итератор или функтор и пусть вызывающие могут передавать ему функторы или итераторы, приспосабливая их по мере необходимости к соответствующему типу.

Сейчас я определяю агрегатор таким образом, чтобы его можно было использовать как выходной итератор или функтор, но это приводит к нежелательной сложности.

1 Ответ

5 голосов
/ 08 февраля 2010
...