1) J'ai de nombreux conteneurs de pointeurs et je fais fréquemment des
itérations pour appeler une méthode. J'aurais souhaité utiliser for_each
mais étant donné que j'appelle des fonctions membres, je ne vais pas
faire un foncteur pour chacune d'entre elle. Comment puis-je faire ?
2) J'itère sur un conteneur (list) de pointeurs et j'appelle une méthode
membre pour chaque élément du conteneur. Le souci est que l'élément
contenu à la possibilité de s'extraire du conteneur, c'est à dire que
erase(iterator) n'est pas appelé au sein de la boucle. Par conséquent,
comme je ne souhaite pas que ma méthode retourne un itérateur, je suis
obligé de récupérer le pointeur suivant à chaque itération. Un peu de
code sera plus clair :
iterator current = conteneur.begin();
if (current != conteneur.end())
{
iterator next = current;
++next;
for (;current != conteneur.end(); current = next++)
(*current)->ma_methode();
}
(J'ai consciemment laissé le next++ qui fait pourtant une incrémentation
sur un itérateur de fin. Quel est le comportement ? Est-ce dangereux de
laisser cela ?)
Ce code n'est pas très joli mais je ne sais pas trop si je peux en faire
quelque chose de mieux. Pour être plus précis, ma_méthode() appelle une
méthode du conteneur qui extrait l'objet car ceci est cohérent avec mon
modèle de simulation.
Cette action est irreversible, confirmez la suppression du commentaire ?
Signaler le commentaire
Veuillez sélectionner un problème
Nudité
Violence
Harcèlement
Fraude
Vente illégale
Discours haineux
Terrorisme
Autre
Benoit Rousseau
Frédéric Mayot wrote:
Bonjour,
Deux questions très simples (enfin je crois...)
1) J'ai de nombreux conteneurs de pointeurs et je fais fréquemment des itérations pour appeler une méthode. J'aurais souhaité utiliser for_each mais étant donné que j'appelle des fonctions membres, je ne vais pas faire un foncteur pour chacune d'entre elle. Comment puis-je faire ? Un foncteur avec un pointeur sur les fonctions de la classe si elles ont
le même proto
2) J'itère sur un conteneur (list) de pointeurs et j'appelle une méthode membre pour chaque élément du conteneur. Le souci est que l'élément contenu à la possibilité de s'extraire du conteneur, c'est à dire que erase(iterator) n'est pas appelé au sein de la boucle. Par conséquent, comme je ne souhaite pas que ma méthode retourne un itérateur, je suis obligé de récupérer le pointeur suivant à chaque itération. Un peu de code sera plus clair : J'ai eu un problème encore plus vissieux où n'importe lequel des
iterateurs pouvait être extrait d'une liste (même le "next" de ton exemple) : voir plus bas.
iterator current = conteneur.begin(); if (current != conteneur.end()) { iterator next = current; ++next;
for (;current != conteneur.end(); current = next++) (*current)->ma_methode(); } Ca semble marcher dans ton cas... Je ne crois pas que le if( !=end() )
soit nécessaire. Le test est fait dans le for ++next se replacera sur conteneur.end() si la liste est vide.
Pour ma part, je simulais un comportement de double-queue (on retire la tête pour la placer à la fin de l'autre queue) avec des fonctions. La suppression se faisait par une fonction qui avancait l'iterateur si c'etait l'iterateur courant qui était effacé. Inconvéniant : 1 seul iterateur possible pour faire une boucle où l'élément peut être retirer (je pouvais toujours faire des boucles si j'étais sûr de ne pas y retirer un élément).
Ca donnait à peu près ca :
iterator head;
iterator list_begin() { return head = conteneur.begin(); }
iterator next() { return ++head; }
remove( Element*e ) { if( *head == e ) { head ++; conteneur.erase( head-1 ); } else { conteneur.remove( e ); } }
(J'ai consciemment laissé le next++ qui fait pourtant une incrémentation sur un itérateur de fin. Quel est le comportement ? Est-ce dangereux de laisser cela ?)
Ce code n'est pas très joli mais je ne sais pas trop si je peux en faire quelque chose de mieux. Pour être plus précis, ma_méthode() appelle une méthode du conteneur qui extrait l'objet car ceci est cohérent avec mon modèle de simulation.
Merci.
Fred
-- -------------------------------------------- Benoît Rousseau : roussebe at spray dot se Jouez en programmant : http://realtimebattle.sourceforge.net/
Frédéric Mayot wrote:
Bonjour,
Deux questions très simples (enfin je crois...)
1) J'ai de nombreux conteneurs de pointeurs et je fais fréquemment des
itérations pour appeler une méthode. J'aurais souhaité utiliser for_each
mais étant donné que j'appelle des fonctions membres, je ne vais pas
faire un foncteur pour chacune d'entre elle. Comment puis-je faire ?
Un foncteur avec un pointeur sur les fonctions de la classe si elles ont
le même proto
2) J'itère sur un conteneur (list) de pointeurs et j'appelle une méthode
membre pour chaque élément du conteneur. Le souci est que l'élément
contenu à la possibilité de s'extraire du conteneur, c'est à dire que
erase(iterator) n'est pas appelé au sein de la boucle. Par conséquent,
comme je ne souhaite pas que ma méthode retourne un itérateur, je suis
obligé de récupérer le pointeur suivant à chaque itération. Un peu de
code sera plus clair :
J'ai eu un problème encore plus vissieux où n'importe lequel des
iterateurs pouvait être extrait d'une liste (même le "next" de ton
exemple) : voir plus bas.
iterator current = conteneur.begin();
if (current != conteneur.end())
{
iterator next = current;
++next;
for (;current != conteneur.end(); current = next++)
(*current)->ma_methode();
}
Ca semble marcher dans ton cas... Je ne crois pas que le if( !=end() )
soit nécessaire. Le test est fait dans le for
++next se replacera sur conteneur.end() si la liste est vide.
Pour ma part, je simulais un comportement de double-queue (on retire la
tête pour la placer à la fin de l'autre queue) avec des fonctions. La
suppression se faisait par une fonction qui avancait l'iterateur si
c'etait l'iterateur courant qui était effacé.
Inconvéniant : 1 seul iterateur possible pour faire une boucle où
l'élément peut être retirer (je pouvais toujours faire des boucles si
j'étais sûr de ne pas y retirer un élément).
Ca donnait à peu près ca :
iterator head;
iterator list_begin() {
return head = conteneur.begin();
}
iterator next() {
return ++head;
}
remove( Element*e ) {
if( *head == e ) {
head ++;
conteneur.erase( head-1 );
} else {
conteneur.remove( e );
}
}
(J'ai consciemment laissé le next++ qui fait pourtant une incrémentation
sur un itérateur de fin. Quel est le comportement ? Est-ce dangereux de
laisser cela ?)
Ce code n'est pas très joli mais je ne sais pas trop si je peux en faire
quelque chose de mieux. Pour être plus précis, ma_méthode() appelle une
méthode du conteneur qui extrait l'objet car ceci est cohérent avec mon
modèle de simulation.
Merci.
Fred
--
--------------------------------------------
Benoît Rousseau : roussebe at spray dot se
Jouez en programmant : http://realtimebattle.sourceforge.net/
1) J'ai de nombreux conteneurs de pointeurs et je fais fréquemment des itérations pour appeler une méthode. J'aurais souhaité utiliser for_each mais étant donné que j'appelle des fonctions membres, je ne vais pas faire un foncteur pour chacune d'entre elle. Comment puis-je faire ? Un foncteur avec un pointeur sur les fonctions de la classe si elles ont
le même proto
2) J'itère sur un conteneur (list) de pointeurs et j'appelle une méthode membre pour chaque élément du conteneur. Le souci est que l'élément contenu à la possibilité de s'extraire du conteneur, c'est à dire que erase(iterator) n'est pas appelé au sein de la boucle. Par conséquent, comme je ne souhaite pas que ma méthode retourne un itérateur, je suis obligé de récupérer le pointeur suivant à chaque itération. Un peu de code sera plus clair : J'ai eu un problème encore plus vissieux où n'importe lequel des
iterateurs pouvait être extrait d'une liste (même le "next" de ton exemple) : voir plus bas.
iterator current = conteneur.begin(); if (current != conteneur.end()) { iterator next = current; ++next;
for (;current != conteneur.end(); current = next++) (*current)->ma_methode(); } Ca semble marcher dans ton cas... Je ne crois pas que le if( !=end() )
soit nécessaire. Le test est fait dans le for ++next se replacera sur conteneur.end() si la liste est vide.
Pour ma part, je simulais un comportement de double-queue (on retire la tête pour la placer à la fin de l'autre queue) avec des fonctions. La suppression se faisait par une fonction qui avancait l'iterateur si c'etait l'iterateur courant qui était effacé. Inconvéniant : 1 seul iterateur possible pour faire une boucle où l'élément peut être retirer (je pouvais toujours faire des boucles si j'étais sûr de ne pas y retirer un élément).
Ca donnait à peu près ca :
iterator head;
iterator list_begin() { return head = conteneur.begin(); }
iterator next() { return ++head; }
remove( Element*e ) { if( *head == e ) { head ++; conteneur.erase( head-1 ); } else { conteneur.remove( e ); } }
(J'ai consciemment laissé le next++ qui fait pourtant une incrémentation sur un itérateur de fin. Quel est le comportement ? Est-ce dangereux de laisser cela ?)
Ce code n'est pas très joli mais je ne sais pas trop si je peux en faire quelque chose de mieux. Pour être plus précis, ma_méthode() appelle une méthode du conteneur qui extrait l'objet car ceci est cohérent avec mon modèle de simulation.
Merci.
Fred
-- -------------------------------------------- Benoît Rousseau : roussebe at spray dot se Jouez en programmant : http://realtimebattle.sourceforge.net/
Samuel Krempp
le Friday 12 December 2003 17:55, écrivit :
1) J'ai de nombreux conteneurs de pointeurs et je fais fréquemment des itérations pour appeler une méthode. J'aurais souhaité utiliser for_each mais étant donné que j'appelle des fonctions membres, je ne vais pas faire un foncteur pour chacune d'entre elle. Comment puis-je faire ?
tu peux générer un objet qui se comportera comme la fonction voulue via son operator() (on appelle ces fonctions des functors..) lors de l'appel à for_each, dans la ligne de code (qui a tendance à devenir longue du coup)
à base d'un ensemble de briques (de la stdlib, de libs supplémentaires, ou encore de tes propres functor de base).
ou (ou et) à l'aide d'un mécanisme dédié à noter en ligne l'expression d'une fonction : les fonctions lambda, et d'une librairie qui amène une syntaxe C++ (et les objets correspondants) pour cela, aussi confortable que le C++ le permet (c'est à dire pas bcp) : boost::lambda http://www.boost.org/libs/lambda/doc/index.html
un exemple d'utilisation de functors construits avec la stdlib (v1, v2, et result sont des containers) std::transform( v1.begin(), v1.end(), v2.begin(), result.begin(), std::compose2( std::divides<int>(), std::bind2nd( std::multiplies<int>(), 200 ), std::identity() ) );
devient avec boost::lambda :
#include <boost/lambda/lambda.hpp> using namespace boost::lambda;
mais bon c'est pas tjrs aussi joli, il faut parfois se contorsionner un peu pour générer le functor qu'on veut avec boost::lambda. Entre autre si on veut appeler une certaine fonction membre sur chaque élément des containers, c'est déja un peu plus verbeux avec bind2nd(mem_fun_ref( <pointeur vers la fonction membre>), arguments... )
class A { public : void set_from_int(int) ; };
... vector<A> v; int x; for_each(v.begin(), v.end(), bind2nd(mem_fun_ref(&A::set_from_int), x) );
Et le pire, c'est si la méthode que tu veux appeler est surchargée, car alors il n'y a aucun moyen pratique C++ de préciser laquelle, on donne le prototype voulu comme ça : void (A::* pmf)(const int) = &A::set_from_int; for_each(v.begin(), v.end(), bind2nd(mem_fun_ref(pmf), x) );
la question était simple (en tout cas pour un matheux, générer des functors, c'est un concept pas sorcier), mais les solutions possibles un peu moins .. j'ai essayé de résumer la situations du mieux que j'ai pu :)
-- Sam
le Friday 12 December 2003 17:55, toto@toto.com écrivit :
1) J'ai de nombreux conteneurs de pointeurs et je fais fréquemment des
itérations pour appeler une méthode. J'aurais souhaité utiliser for_each
mais étant donné que j'appelle des fonctions membres, je ne vais pas
faire un foncteur pour chacune d'entre elle. Comment puis-je faire ?
tu peux générer un objet qui se comportera comme la fonction voulue via son
operator() (on appelle ces fonctions des functors..) lors de l'appel à
for_each, dans la ligne de code (qui a tendance à devenir longue du coup)
à base d'un ensemble de briques (de la stdlib, de libs supplémentaires, ou
encore de tes propres functor de base).
ou (ou et) à l'aide d'un mécanisme dédié à noter en ligne l'expression d'une
fonction : les fonctions lambda, et d'une librairie qui amène une syntaxe
C++ (et les objets correspondants) pour cela, aussi confortable que le C++
le permet (c'est à dire pas bcp) : boost::lambda
http://www.boost.org/libs/lambda/doc/index.html
un exemple d'utilisation de functors construits avec la stdlib
(v1, v2, et result sont des containers)
std::transform( v1.begin(), v1.end(), v2.begin(), result.begin(),
std::compose2(
std::divides<int>(),
std::bind2nd( std::multiplies<int>(), 200 ),
std::identity() ) );
devient avec boost::lambda :
#include <boost/lambda/lambda.hpp>
using namespace boost::lambda;
mais bon c'est pas tjrs aussi joli, il faut parfois se contorsionner un peu
pour générer le functor qu'on veut avec boost::lambda.
Entre autre si on veut appeler une certaine fonction membre sur chaque
élément des containers, c'est déja un peu plus verbeux avec
bind2nd(mem_fun_ref( <pointeur vers la fonction membre>), arguments... )
class A {
public :
void set_from_int(int) ;
};
...
vector<A> v;
int x;
for_each(v.begin(), v.end(), bind2nd(mem_fun_ref(&A::set_from_int), x) );
Et le pire, c'est si la méthode que tu veux appeler est surchargée, car
alors il n'y a aucun moyen pratique C++ de préciser laquelle, on donne le
prototype voulu comme ça :
void (A::* pmf)(const int) = &A::set_from_int;
for_each(v.begin(), v.end(), bind2nd(mem_fun_ref(pmf), x) );
la question était simple (en tout cas pour un matheux, générer des functors,
c'est un concept pas sorcier), mais les solutions possibles un peu
moins ..
j'ai essayé de résumer la situations du mieux que j'ai pu :)
1) J'ai de nombreux conteneurs de pointeurs et je fais fréquemment des itérations pour appeler une méthode. J'aurais souhaité utiliser for_each mais étant donné que j'appelle des fonctions membres, je ne vais pas faire un foncteur pour chacune d'entre elle. Comment puis-je faire ?
tu peux générer un objet qui se comportera comme la fonction voulue via son operator() (on appelle ces fonctions des functors..) lors de l'appel à for_each, dans la ligne de code (qui a tendance à devenir longue du coup)
à base d'un ensemble de briques (de la stdlib, de libs supplémentaires, ou encore de tes propres functor de base).
ou (ou et) à l'aide d'un mécanisme dédié à noter en ligne l'expression d'une fonction : les fonctions lambda, et d'une librairie qui amène une syntaxe C++ (et les objets correspondants) pour cela, aussi confortable que le C++ le permet (c'est à dire pas bcp) : boost::lambda http://www.boost.org/libs/lambda/doc/index.html
un exemple d'utilisation de functors construits avec la stdlib (v1, v2, et result sont des containers) std::transform( v1.begin(), v1.end(), v2.begin(), result.begin(), std::compose2( std::divides<int>(), std::bind2nd( std::multiplies<int>(), 200 ), std::identity() ) );
devient avec boost::lambda :
#include <boost/lambda/lambda.hpp> using namespace boost::lambda;
mais bon c'est pas tjrs aussi joli, il faut parfois se contorsionner un peu pour générer le functor qu'on veut avec boost::lambda. Entre autre si on veut appeler une certaine fonction membre sur chaque élément des containers, c'est déja un peu plus verbeux avec bind2nd(mem_fun_ref( <pointeur vers la fonction membre>), arguments... )
class A { public : void set_from_int(int) ; };
... vector<A> v; int x; for_each(v.begin(), v.end(), bind2nd(mem_fun_ref(&A::set_from_int), x) );
Et le pire, c'est si la méthode que tu veux appeler est surchargée, car alors il n'y a aucun moyen pratique C++ de préciser laquelle, on donne le prototype voulu comme ça : void (A::* pmf)(const int) = &A::set_from_int; for_each(v.begin(), v.end(), bind2nd(mem_fun_ref(pmf), x) );
la question était simple (en tout cas pour un matheux, générer des functors, c'est un concept pas sorcier), mais les solutions possibles un peu moins .. j'ai essayé de résumer la situations du mieux que j'ai pu :)
-- Sam
Loïc Joly
Frédéric Mayot wrote:
Bonjour,
Deux questions très simples (enfin je crois...)
1) J'ai de nombreux conteneurs de pointeurs et je fais fréquemment des itérations pour appeler une méthode. J'aurais souhaité utiliser for_each mais étant donné que j'appelle des fonctions membres, je ne vais pas faire un foncteur pour chacune d'entre elle. Comment puis-je faire ?
Créer un foncteur, soit avec les fonctions de la bibliothèque standard, soit autrement. Pour ça, j'aime bien boost::bind, qui m'a l'air moins "louche" que boost::lambda dont parle Samuel Krempp dans sa réponse, et reste agréable à utiliser. Ca donne :
1) J'ai de nombreux conteneurs de pointeurs et je fais fréquemment des
itérations pour appeler une méthode. J'aurais souhaité utiliser for_each
mais étant donné que j'appelle des fonctions membres, je ne vais pas
faire un foncteur pour chacune d'entre elle. Comment puis-je faire ?
Créer un foncteur, soit avec les fonctions de la bibliothèque standard,
soit autrement. Pour ça, j'aime bien boost::bind, qui m'a l'air moins
"louche" que boost::lambda dont parle Samuel Krempp dans sa réponse, et
reste agréable à utiliser. Ca donne :
1) J'ai de nombreux conteneurs de pointeurs et je fais fréquemment des itérations pour appeler une méthode. J'aurais souhaité utiliser for_each mais étant donné que j'appelle des fonctions membres, je ne vais pas faire un foncteur pour chacune d'entre elle. Comment puis-je faire ?
Créer un foncteur, soit avec les fonctions de la bibliothèque standard, soit autrement. Pour ça, j'aime bien boost::bind, qui m'a l'air moins "louche" que boost::lambda dont parle Samuel Krempp dans sa réponse, et reste agréable à utiliser. Ca donne :