Функтор C++ для вывода адаптера итератора

Учитывая функтор, подходящий для использования с std::for_each и друзья:

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

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

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

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

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

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  GetItems(It out) {
    MutexGuard guard(mutex);
    std::copy(items.begin(), items.end(), out);
}

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

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

std::set 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());

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

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

7
задан Community 23 May 2017 в 12:15
поделиться