Accueil
|_Accueil Langage C++ |_La librairie <algorithm> |_std::copy |_std::copy_backward |_std::fill |_std::for_each |
Fonction std::for_eachEntête à inclure#include <algorithm> Fonction std::for_eachtemplate <typename IT, typename FUNCTION_OBJECT> FUNCTION_OBJECT std::for_each( IT begin, IT end, FUNCTION_OBJECT fo );
Cette fonction permet d'appliquer un même traitement à un ensemble d'éléments d'une collection. Par l'aspect générique de cette
fonction, elle peut être utilisées sur tous types de collections comptatibles avec le modèle STL
(
Afin de correctement comprendre le fonctionnement de la fonction template <typename IT, typename FUNCTION_OBJECT> inline FUNCTION_OBJECT for_each( IT current, IT end, FUNCTION_OBJECT fo ) { while( current != end ) { fo( *current ++ ); } return fo; } L'idée est simple : un « function object » est un élément sur lequel on peut chercher à lancer un appel en utilisant les parenthèses. Deux alternatives peuvent être envisagées :
Vous comprenez donc mieux l'origine du nom « function object ». Pour la première solution, je pense qu'elle se passe de commentaire. Par contre, la seconde justifie le petit exemple qui suit. #include <iostream> #include <string> using namespace std; class Demo { public: void operator()( const string & parameter ) { cout << "in operator() with " << parameter << endl; } }; int main() { Demo instance; instance( "short syntax" ); instance.operator()( "expanded syntax" ); return 0; } Et voici les résultats produits par cet exemple. $> g++ -o Sample Sample.c -std=c++11 $> ./Sample in operator() with short syntax in operator() with expanded syntax $> Pourquoi accepter ces deux possibilités (fonction ou objet) ? Pour répondre de manière adaptée à différents scénario. Si chaque éléments à traiter peut l'être indépendemment des autres, alors passer un pointeur sur fonction sera très certainement la meilleure solution étant donné que c'est la plus simple à coder. Par contre, si un contexte doit être conservé entre chaque appel, alors l'utilisation d'un objet sera plus utile : effectivement, l'objet pourra porter votre contexte par le biais de ses attributs. A chaque exécution de l'opérateur (), le contexte sera très facilement accessible. Paramètres
Valeur de retour
Cette fonction renvoie le « Exemple de code#include <algorithm> #include <iostream> #include <iterator> #include <list> #include <string> using namespace std; /* std::for_each implementation is like this. template <typename IT, typename FUNCTION_OBJECT> inline FUNCTION_OBJECT for_each2( IT current, IT end, FUNCTION_OBJECT fo ) { while( current != end ) { fo( *current ++ ); } return fo; } */ void charToUpper( char & c ) { if ( c>='a' && c<='z' ) { c &= 223; } } class StringToUpper { int cpt = 0; public: inline void operator()( string & str ) { cout << "Not a function, but an instance" << endl; cpt++; str[0] = cpt + 0x30; for_each( str.begin(), str.end(), charToUpper ); } }; int main() { list<string> maListe; maListe.push_front( "x_C++" ); maListe.push_front( "x_Python" ); maListe.push_back( "x_Java" ); maListe.push_back( "x_C Sharp" ); for_each( maListe.begin(), maListe.end(), StringToUpper() ); copy( maListe.begin(), maListe.end(), ostream_iterator<string>(cout," - ") ); cout << endl; return 0; }
ATTENTION : cet exemple utilise une nouveauté introduite avec la version 2011 du standard C++ (l'initialisation de l'attribut
lors de sa déclaration). Avec la chaine de compilation $> g++ -o Sample Sample.c -std=c++11 $> ./Sample Not a function, but an instance Not a function, but an instance Not a function, but an instance Not a function, but an instance 1_PYTHON - 2_C++ - 3_JAVA - 4_C SHARP - $> Sujets connexes |
Améliorations / Corrections
Vous avez des améliorations (ou des corrections) à proposer pour ce document : je vous remerçie par avance de m'en faire part, cela m'aide à améliorer le site.
Emplacement :
Description des améliorations :