2010-02-07 3 views
7

einen Funktor geeignet für den Einsatz mit std::for_each und Freunden Gegeben:C++ Funktors zur Ausgabe von Iterator-Adapter

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

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

Gibt es einen Standard-Weg, dies in einen Output-Iterator geeignet für mit std::copy und Freunden Gebrauch zu konvertieren? (Oder die entgegengesetzte Anpassung) Etwas wie:

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

Welche der Funktor jedes Mal, wenn ein Wert, der dem Iterator zugeordnet nennen würde:

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

Oder alternativ:

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

Hintergrund:

Ich habe eine Klasse, die eine Sammlung mit einem Output-Iterator aussetzt:

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

Dieser Anrufer Zugriff auf die Elemente erhalten können, ohne sie zu zwingen, einen bestimmten Behältertyp zu verwenden und ohne Herumspielen mit Sperr- oder anderen internen Details.

zum Beispiel nur Unikate erhalten:

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

Dies schlägt die Hölle aus:

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

Jetzt möchte ich in der Lage sein, auch eher diese Elemente zusammenfassen, als sie zu kopieren. (Siehe this question). Wo würde ich normalerweise etwas tun:

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

Jetzt konnte ich zwei verschiedene Methoden für die gleichen Datenelemente machen, eine, die std::copy und nennt die std::for_each nennt, aber es wäre schön, der Lage sein, nur eine solche zu definieren, Methode, die einen Iterator oder einen Funktor verwendet und Anrufer in die Lage versetzt werden, entweder Funktoren oder Iteratoren an sie zu übergeben und sie dann an den entsprechenden Typ anzupassen.

Was ich jetzt mache, ist, den Aggregator so zu definieren, dass er entweder als Output-Iterator oder als Funktor verwendet werden kann, aber dies führt zu unerwünschter Komplexität.

+0

Immer noch nicht sehr gut ... for_each, wie Sie darauf hinweisen, ändert die Werte nicht, so dass der Operator() void (nichts) zurückgibt, und akzeptieren ein T const & (nichts zu ändern) Was ist also der Wert der auszugebenden Kopiermethode? –

+0

@Diego Der Funktor ändert seine Argumente nicht, aber ändert seinen internen Zustand. Im Gegensatz zu einer typischen Kopie ist die Ausgabe der Status des Funktors, nicht eine Reihe von Elementen. –

Antwort

5
+0

Okay, das ist nur peinlich. Ich schaute direkt auf die Boost-Iterator-Dokumente und übersprang das offensichtlich. Ich glaube, ich suchte nach "Funktor" und sonst nichts. –