(STL) algo copy_if

algo copy_if (STL) - C++ - Programmation

Marsh Posté le 21-06-2004 à 23:07:46    

Pouvez vous m'aider à completer ce fragment de code.

Code :
  1. bool p( const T& );
  2. list<T> l1;
  3. list<T> l2;
  4. // construire l2 à partir des éléments de l1 si le prédicat p est vrai
  5. ....( l1.begin(), l1.end(), .... );


 
Il me semble que cela est possible en une seule instruction mais je ne me rappelle plus comment faire.


Message édité par xterminhate le 11-08-2004 à 01:33:33

---------------
Cordialement, Xterm-in'Hate...
Reply

Marsh Posté le 21-06-2004 à 23:07:46   

Reply

Marsh Posté le 21-06-2004 à 23:12:27    

avec un algo genre remove_copy_if + un back_inserter


Message édité par Taz le 21-06-2004 à 23:26:11
Reply

Marsh Posté le 21-06-2004 à 23:13:53    

Et bien c'est ce à quoi j'ai pensé en premier et en relisant le manuel de transform, je n'ai pas trouvé la bonne méthode :/


---------------
Cordialement, Xterm-in'Hate...
Reply

Marsh Posté le 21-06-2004 à 23:16:42    

Comment associer un predicat à tranform/back_inserter ?


Message édité par xterminhate le 21-06-2004 à 23:16:53

---------------
Cordialement, Xterm-in'Hate...
Reply

Marsh Posté le 21-06-2004 à 23:26:26    

wait l'exemple arrive

Reply

Marsh Posté le 21-06-2004 à 23:37:17    

Code :
  1. #include <list>
  2. #include <algorithm>
  3. #include <iterator>
  4. #include <iostream>
  5. #include <functional>
  6. namespace
  7. {
  8.   template<typename InputIterator,
  9.    typename OutputIterator,
  10.    typename Predicate>
  11.   inline void copy_if(InputIterator first, InputIterator last,
  12.        OutputIterator out,
  13.        Predicate p)
  14.   {
  15.     while(first != last)
  16.       {
  17. if( p(*first) )
  18.   {
  19.     *out++ = *first;
  20.   }
  21. ++first;
  22.       }
  23.   }
  24.   template<typename T>
  25.   inline bool selector(const T &t)
  26.   {
  27.     return t & 1;
  28.   }
  29. }
  30. int main()
  31. {
  32.   int integers[] = {1, 2, 3, 4, 5, 6};
  33.   // j'utilise la liste pour te faire plaisir, sinon y en a pas besoin
  34.   // autant tout sortir sur std::cout
  35.   typedef std::list<int> Liste;
  36.   Liste res;
  37.   std::remove_copy_if(&integers[0],
  38.   &integers[0] + sizeof integers / sizeof integers[0],
  39.   std::back_inserter(res),
  40.   selector<Liste::value_type> );
  41.   std::copy(res.begin(), res.end(),
  42.     std::ostream_iterator< Liste::value_type >(std::cout, ", " ));
  43.   std::cout << std::endl;
  44.   res.clear();
  45.   copy_if(&integers[0],
  46.   &integers[0] + sizeof integers / sizeof integers[0],
  47.   std::back_inserter(res),
  48.   selector<Liste::value_type> );
  49.   std::copy(res.begin(), res.end(),
  50.     std::ostream_iterator< Liste::value_type >(std::cout, ", " ));
  51.   std::cout << std::endl;
  52. }


 
bon j'ai pas poussé plus loin l'exemple full stl, il aurait fallut faire la négation. tu vois bien qu'avec un petit algo simple fait maison, on y arrive. la STL n'est pas complète loin de là : il aurait fallut passer par boost pour faire ça un peu plus proprement. y en a marre de pas avoir de begin(tab) et de end(tab) de devoir se taper l'écriture C ...

Reply

Marsh Posté le 21-06-2004 à 23:38:21    

c'est aussi facile de ne bricoler un petit FilteringOutputIterator auquel cas, un simple std::copy fonctionnera super bien

Reply

Marsh Posté le 21-06-2004 à 23:45:22    

Bien, la STL manque vraiment d'un copy_if comme tu l'as décrit.
 
On trouve la définition de FilteringOutputIterator sur SGI ?


---------------
Cordialement, Xterm-in'Hate...
Reply

Marsh Posté le 21-06-2004 à 23:51:04    

Merci pour l'exemple, je range ton copy_if dans ma boite à outils à coté de la STL ;)


---------------
Cordialement, Xterm-in'Hate...
Reply

Marsh Posté le 21-06-2004 à 23:52:35    

nulle part un FilteringOuputIterator, c'est juste un OutputIterator qui filtre ce qu'on lui demande de sortir

Reply

Marsh Posté le 21-06-2004 à 23:52:35   

Reply

Marsh Posté le 22-06-2004 à 00:11:48    

Code :
  1. #include <list>
  2. #include <algorithm>
  3. #include <iterator>
  4. #include <iostream>
  5. namespace
  6. {
  7.   template<typename T>
  8.   inline bool selector(const T &t)
  9.   {
  10.     return t & 1;
  11.   }
  12.   template<typename T,
  13.    typename OutputIterator,
  14.    typename Predicate>
  15.   struct FilteringOutputIterator
  16.   {
  17.     OutputIterator out;
  18.     Predicate pred;
  19.     FilteringOutputIterator(OutputIterator o, Predicate p)
  20.       : out(o), pred(p)
  21.     { }
  22.     FilteringOutputIterator&
  23.     operator=(const T &t)
  24.     {
  25.       if( pred(t) ) *out++ = t;
  26.       return *this;
  27.     }
  28.     FilteringOutputIterator&
  29.     operator*() { return *this; }
  30.     FilteringOutputIterator&
  31.     operator++() { return *this; }
  32.     FilteringOutputIterator&
  33.     operator++(int) { return *this; }
  34.   };
  35.    template<typename T,
  36.    typename OutputIterator,
  37.    typename Predicate>
  38.    inline FilteringOutputIterator<T, OutputIterator, Predicate>
  39.    FilterOutput(OutputIterator out, Predicate pred)
  40.    { return FilteringOutputIterator<T, OutputIterator, Predicate>(out, pred); }
  41. }
  42. int main()
  43. {
  44.   const int integers[] = {1, 2, 3, 4, 5, 6};
  45.   // j'utilise la liste pour te faire plaisir, sinon y en a pas besoin
  46.   // autant tout sortir sur std::cout
  47.   typedef std::list<int> Liste;
  48.   Liste res;
  49.   std::copy(&integers[0],
  50.     &integers[0] + sizeof integers / sizeof integers[0],
  51.     FilterOutput<Liste::value_type>(std::back_inserter(res),
  52.         selector<Liste::value_type> )
  53.     );
  54.   std::copy(res.begin(), res.end(),
  55.     std::ostream_iterator< Liste::value_type >(std::cout, ", " ));
  56.   std::cout << std::endl;
  57. }


Message édité par Taz le 22-06-2004 à 07:52:13
Reply

Marsh Posté le 22-06-2004 à 07:21:18    

Merci pour l'exemple. C'est instructif.


---------------
Cordialement, Xterm-in'Hate...
Reply

Marsh Posté le 22-06-2004 à 11:34:53    

Taz a écrit :

Code :
  1. template<typename InputIterator,
  2.    typename OutputIterator,
  3.    typename Predicate>
  4.   inline void copy_if(InputIterator first, InputIterator last,
  5.        OutputIterator out,
  6.        Predicate p)
  7.   {
  8.     while(first != last)
  9.       {
  10. if( p(*first) )
  11.   {
  12.     *out++ = *first;
  13.   }
  14. ++first;
  15.       }
  16.   }




La version Stroustrup retourne out à la fin et pas void.


Message édité par HelloWorld le 22-06-2004 à 11:35:10

---------------
FAQ fclc++ - FAQ C++ - C++ FAQ Lite
Reply

Marsh Posté le 24-06-2004 à 07:39:40    

ça me fait une belle jambe ... surtout si tu crois que j'ai besoin d'un livre ou d'une quelconque documentation pour écrire ce genre de chose ...

Reply

Marsh Posté le 24-06-2004 à 21:53:40    

Comment se passer de l'appel back_inserter() en argument de copy_if ?
 
Est-ce que passer l'iterateur en référence et fournir un iterateur à l'aide de begin() conviendrait ?


---------------
Cordialement, Xterm-in'Hate...
Reply

Marsh Posté le 24-06-2004 à 21:58:13    

non. il faut fournir un itérateur d'insertion un back/front/<rien> inserter doit donc être utilisé

Reply

Marsh Posté le 25-06-2004 à 00:05:15    

Taz a écrit :

ça me fait une belle jambe ... surtout si tu crois que j'ai besoin d'un livre ou d'une quelconque documentation pour écrire ce genre de chose ...


C'est pas ma faute si t'es nul en C++ [:spamafote]


---------------
FAQ fclc++ - FAQ C++ - C++ FAQ Lite
Reply

Marsh Posté le 25-06-2004 à 00:33:04    

désolé, j'ai rien pour relever

Reply

Marsh Posté le 25-06-2004 à 03:54:23    

fight, fight

Reply

Marsh Posté le 25-06-2004 à 14:45:16    

Taz a écrit :

désolé, j'ai rien pour relever


Ta réaction était tellement stupide que j'ai essayé de l'être encore plus. Ma réponse s'adressait à personne en particulier, c'était dans un but de précision. Maitenant si tu te vexe parce qu'on post une remarque sur ton code, t'as qu'à créer une catégorie Taz où y'a que toi qui a le droit de répondre. Ta susceptibilité à 2 balles tu peux te la garder.
C'est pas tout d'avoir le style grande gueule, faut pas venir pleurnicher quand ça t'arrives.


---------------
FAQ fclc++ - FAQ C++ - C++ FAQ Lite
Reply

Marsh Posté le 25-06-2004 à 15:02:49    

:heink:  
je sais pas ou t'as vu que je pleurnichais... mais bon si ça t'amuse que penser que je suis un capricieux caractériel qui gueule sur les autres mais qui rentre pleurer chez ça mère dès qu'on lui quelque chose ...
 
d'ailleurs j'ai toujours pas compris ton intervention ...

Reply

Marsh Posté le 27-06-2004 à 01:04:42    

Y'a rien à comprendre. Le but était de compléter ta réponse initiale.


---------------
FAQ fclc++ - FAQ C++ - C++ FAQ Lite
Reply

Marsh Posté le 11-08-2004 à 01:30:30    

J'ai adapté le code de copy_if pour réaliser un algo légèrement différent. Il s'agit cette fois de copier les éléments d'un conteneur vers un autre en fonction du type de leurs éléments.
 
Concrètement, je construit une list<D*> à partir des éléments d'une list<B*> si la conversion B* vers D* est possible.
 
Cela semble foncitonner correctement :
 

Code :
  1. template<typename T, typename InputIterator,typename OutputIterator>
  2. inline void transform_if_type(InputIterator first, InputIterator last, OutputIterator out)
  3. {
  4. while(first != last)
  5. {
  6.  if( T p = dynamic_cast<T>( *first ) ) 
  7.   *out++ = p;
  8.  ++first;
  9. }
  10. }


 
L'utilisation de cette algo est équivalente aux exemples précédents du post : transform_if_type<D*>( .., .., back.. );
 
Par contre, je me demande si je ne suis pas encore passé à coté d'un algo plus simple, plus évident.


Message édité par xterminhate le 11-08-2004 à 01:32:54
Reply

Marsh Posté le 11-08-2004 à 07:33:02    

ça peut aller ça. sauf niveau typage, c'est un joyeux bordel pour deviner qui est qui, le problème étant que rien ne mets en relation OutputIterator et T, tu es donc obligé de le spécifier. donc veille bien à utilise ::value_type.  
 
transform_if_is_instance :P est plus correct
 
l'important ce que ça te satisfasse

Reply

Marsh Posté le 11-08-2004 à 18:07:07    

En reformulant qq peu les types, j'obtiens un algo assez spécialisé. Le compilateur refuse de templatiser le de conteneur, dommage! Sinon j'obtiens un warning du genre : `typename std::list<TB*, std::allocator<TB*>>::const_iterator' is implicitly a typename
 

Code :
  1. template< typename TB, typename TD, template < typename X > class C  >
  2. inline void transform_if_is_instance( typename C<TB*>::const_iterator first, typename C<TB*>::const_iterator last, back_insert_iterator< C<TD*> > out )
  3. {
  4. while(first != last)
  5. {
  6.  if( TD* p = dynamic_cast<TD*>( *first ) ) 
  7.   *out++ = p;
  8.  ++first;
  9. }
  10. }


--edit1 : correction warning / ajout de typename.
--edit2 : retrait spécialisation / ajout template template.


Message édité par xterminhate le 11-08-2004 à 19:29:18

---------------
Cordialement, Xterm-in'Hate...
Reply

Marsh Posté le 11-08-2004 à 18:27:30    

utilise typename :o (voir mon topic)
 
bah y a pas besoin de restreindre a std::list :o

Reply

Marsh Posté le 11-08-2004 à 19:12:14    

ok pour typename.
 
Comment faire pour eviter la spécialisation ?


---------------
Cordialement, Xterm-in'Hate...
Reply

Marsh Posté le 11-08-2004 à 19:15:17    

en déclarant un paramètre template template

Reply

Marsh Posté le 11-08-2004 à 19:17:33    

C'est bien ce dont j'ai besoin ! Je ne pensais pas que c'etait possible... je vais essayer de trouver.


---------------
Cordialement, Xterm-in'Hate...
Reply

Marsh Posté le 11-08-2004 à 19:20:42    

template< template<typename T> class Sequence >

Reply

Marsh Posté le 11-08-2004 à 19:28:49    

Voila ! Dans le template template, typename ne peut pas être utilisé...bizarre.


---------------
Cordialement, Xterm-in'Hate...
Reply

Marsh Posté le 11-08-2004 à 20:01:47    

Je suis impresionné ... ;)
Un jour j'y arriverai à comprendre comment fonctionne les templates !  :ange:  
Enfin peut-être ..  :lol:  

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed