Newsgroup: it.comp.lang.c++
Titolo: problema con mem_fun

salve a tutti,
partendo dal seguente programmino funzionante :
[CPP]
#include <iostream>
#include <string>
#include <fstream>
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
using namespace std;
void record(const string &);
void print(const pair<string, int> &);
map<string,int> frequenza;
int main(int argc, char **argv)
{
      if (argc!=2)
      {
            cerr << argv[0] << " <nomedelfile>" << endl;
            exit(1);
      }
      ifstream in(argv[1]);
      istream_iterator<string> it(in);
      istream_iterator<string> eos;
      vector<string> b(it,eos);
      for_each(b.begin(),b.end(),record);
      for_each(frequenza.begin(),frequenza.end(),print);
      return 0;
}
void record(const string &s)
{
      frequenza[s]++;
}
void print(const pair<string, int> &r)
{
      cout << r.first << ' ' << r.second << endl;
}
[/CPP]
ho cercato di applicarlo ad una classe ...
[FILE Occur.h]
#include <iostream>
#include <string>
#include <fstream>
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
using namespace std;
class Occur
{
        private:
        const char *filename;
        vector<string> vett;
        map<string,int> frequenza;
        public:
        Occur(const char *s) : filename(s) {}
        void Parse(void);
        void Stampa(const pair<string,int> &);
};
[FILE Occur.cpp]
#include "Occur.h"
void Occur::Stampa(const pair<string,int> &r)
{
        cout << r.first << ' ' << r.second << endl;
}
void Occur::Parse(void)
{
        ifstream in(filename);
        istream_iterator<string> it(in);
        istream_iterator<string> eos;
        vett.assign(it,eos);
        for (vector<string>::iterator si=vett.begin(); si!=vett.end(); si++)
                frequenza[*si]++;
        for_each(frequenza.begin(),frequenza.end(),mem_fun(&Occur::Stampa));
}
[FILE Main.cpp]
#include "Occur.h"
int main(int argc, char **argv)
{
        if (argc!=2)
        {
                cerr << argv[0] << " <nomedelfile>" << endl;
                exit(1);
        }
        Occur ant(argv[1]);
        ant.Parse();
        return 0;
}
mi da questo errore:
/usr/include/g++/stl_algo.h: In function `class mem_fun1_t<void,Occur,
....
Occur.cpp:20:   instantiated from here
/usr/include/g++/stl_algo.h:83: no match for call to
`(mem_fun1_t<void,Occur,con
st
pair<basic_string<char,string_char_traits<char>,__default_alloc_template<fals
e,0> >,int> &>) (pair<const
basic_string<char,string_char_traits<char>,__default
_alloc_template<false,0> >,int> &)'
/usr/include/g++/stl_function.h:602: candidates are: void
mem_fun1_t<void,Occur,const
pair<basic_string<char,string_char_traits<char>,__default_alloc_template<f
alse,0> >,int> &>::operator ()(Occur *, const
pair<basic_string<char,string_char
_traits<char>,__default_alloc_template<false,0> >,int> &) const
mi date una mano a capire ??
grazie anticipate ...
-- 
#include <stdio.h>
int main(void){char c[]={10,65,110,116,111,110,105,111,32,98,97,114,98,111,110,
101,32,60,104,105,110,100,101,109,105,116,64,116,105,115,99,97,108,105,110,101,
116,46,105,116,62,10,10,0};printf("%s",c);return 0;}

 wrote in message
news:bvlt7a$tluc0$1...@ID-144796.news.uni-berlin.de...

Il template for_each() chiama  il functor passandogli il reference
restituito dall'iterator. Quindi come prima cosa e' necessario utilizzate
mem_fun_ref
piuttosto che mem_fun.
  // TEMPLATE FUNCTION for_each
template<class _II, class _Fn> inline
 _Fn for_each(_II _F, _II _L, _Fn _Op)
 {for (; _F != _L; ++_F)
  _Op(*_F);
 return (_Op); }
La spiegazione e' un po' complicata, diciamo che mem_ref e mem_fun sono
function adapter correlati o legati alla collection che stai utilizzando.
In altre parole se crei una collection di Occur ed esegui una iterazione su
una collection di tale classe il tutto dovrebbe funzionare.
Il template mem_fun_ref crea un adapter mem_fun_ref_t oppure mem_fun_ref1_t
che memorizza il puntatore alla funzione membro della tua classe (nel tuo
caso Occur::Stampa) e
definisce l'operatore () avente come parametro un reference della tua classe
Occur.
Ad ogni itarazione viene chiamata questultima functione (quella di
mem_fun_ref_t) e passato come parametro il reference restituito
dall'iteratore.
L'operatore () di mem_fun_ref_t non fa altro che chiamare la funzione che ha
memorizzato (mediante class pointer) per 'istantza della classa che gli e'
stata passata come parametro.
template<class _R, class _Ty>
 class mem_fun_ref_t : public unary_function<_Ty, _R> {
public:
 explicit mem_fun_ref_t(_R (_Ty::*_Pm)())
  : _Ptr(_Pm) {}
 _R operator()(_Ty& _X) const
  {return ((_X.*_Ptr)()); }
private:
 _R (_Ty::*_Ptr)();
 };
Mi rendo conto di essere stato contorto piu' o meno come lo sono le STL :-)
Ciao
Fabio
La prima crea mem_fun_ref_t il cui operatore () vuole come parametro un
tiopo passato per reference la second crea  valore passato per reference
Il funzione template "mem_fun" e' utilizzato per creare/ritornare una classe
templete "mem_fun1_t".
Quest'ultima non fa altro che memorizzare un puntatore alla funzione membro
passata come parametro (class pointer) ed esporre l'operatore () piu' o meno
in questo modo:
R operator()(Ty* P, A Arg) const
{
   return ( P->*Ptr_)(Arg);
}
dove Ty e' il tipo,
 R operator()(T* P) const
{
    return ( P->*_Ptr)();
}

 Fabio
ciao e grazie mille per l'aiuto ....
