7 votes

Adapteur d'itérateur de sortie de foncteur C++

Étant donné un foncteur approprié pour être utilisé avec std::for_each et ses amis :

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

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

Existe-t-il un moyen standard de convertir ceci en un itérateur de sortie approprié pour être utilisé avec std::copy et ses amis? (ou l'adaptation inverse) Quelque chose comme :

std::copy(v.begin(), v.end(), itérateur_sortie_foncteur(Foo()));

Qui appellerait le foncteur à chaque fois qu'une valeur est assignée à l'itérateur :

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

Ou, en alternative :

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

Contexte :

J'ai une classe qui expose une collection en utilisant un itérateur de sortie :

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

Cela permet aux appelants d'accéder aux éléments sans les forcer à utiliser un type de conteneur spécifique et sans se mêler de verrouillage ou d'autres détails internes.

Par exemple, pour obtenir uniquement des éléments uniques :

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

C'est bien mieux que :

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

Maintenant, je veux aussi être capable d'agréger ces éléments, plutôt que de les copier. (Voir cette question). Là où je ferais normalement quelque chose comme :

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

Maintenant, je pourrais créer deux méthodes séparées pour les mêmes éléments de données, une qui appelle std::copy et une qui appelle std::for_each mais ce serait bien de pouvoir définir juste une seule telle méthode, en utilisant un itérateur ou un foncteur, et permettre aux appelants de passer soit des foncteurs soit des itérateurs, en les adaptant au type approprié si nécessaire.

Actuellement, je définis l'agrégateur de sorte qu'il puisse être utilisé comme un itérateur de sortie ou un foncteur, mais cela entraîne une complexité non désirée.

5voto

villintehaspam Points 4470

Que diriez-vous de boost::function_output_iterator?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X