Newsgroup: it.comp.lang.c++
Titolo: funzioni oggetto

Qual'è la differenza tra una funzione e un oggetto funzione (con il
solo operator() implementato)? Perchè alcuni algoritmi (vedi sort)
richiedono un oggetto funzione e non una semplice funzione?

 richiedono un oggetto funzione e non una semplice funzione?
Se il gcc 2.95 non è troppo errato, sort non richiede un oggetto
funzione, ma basta una funzione. Vedi questo codice:
#include <algorithm>
#include <vector>
using namespace std;
bool eq (int a, int b)
{
    return a == b;
}
int main ()
{
    vector <int> v;
    v.push_back (3);
    v.push_back (6);
    v.push_back (1);
    v.push_back (4);
    v.push_back (5);
    v.push_back (2);
    sort (v.begin (), v.end (), eq);
    return 0;
}
Ovviamente è un esempio molto stupido, ma funziona.
Gli oggetti funzione hanno una grande utilità: permettono di avere più
di una funzione (operator ()). Ti posto un esempio di Stroustrup un po'
ampliato:
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
template <typename T> class Sum {
        T res;
public:
        Sum (T i = 0) : res (i) {}
        void operator () (T x) { res += x; }
        T result () { return res; }
};
int main ()
{
    vector <int> c;
    c.push_back (3);
    c.push_back (4);
    c.push_back (5);
    Sum <int> s;
    for_each (c.begin (), c.end (), s);
    cout << s.result () << endl;
}
In pratica, grazie ad un oggetto funzione puoi fare molte operazione
aggiuntive, rispetto ad una semplice funzione.
-- 
Andrea Bergia - studente              Linux Registred User #281550
"The one thing we're all waiting for, is peace on Earth and an end to
war,
it's a miracle we need, the miracle, the miracle, 
Peace on earth and end to war today,
That time will come one day you'll see when we can all be friends"

 richiedono un oggetto funzione e non una semplice funzione?
Non è vero che std::sort() richieda per forza un oggetto funzione.
Guarda questo esempio:
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
inline bool Maggiore( int n1, int n2 ) { return n1 >= n2; }
int main()
{
    int a[] = { 7, 5, 9, 2, 4, 8 };
    std::vector < int > v( a, a + sizeof( a ) / sizeof( a[ 0 ] ) );
//    std::sort( v.begin(), v.end(), std::greater < int >() );
    std::sort( v.begin(), v.end(), Maggiore );
    for ( std::vector < int >::iterator i = v.begin(); i != v.end(); ++i
)
        std::cout << *i << '\n';
    return 0;
}
Uno dei motivi per cui vengono utilizzati gli oggetti funzione è che
questi possono essere dei templates e quindi è possibile utilizzarli
qualunque sia il tipo per cui viene istanziato il template contenitore.
EMG
--
EMAG Software Homepage:     
http://www.emagsoftware.it
The EMG's ZX-Spectrum Page: 
http://www.emagsoftware.it/spectrum
The Best of Spectrum Games: 
http://www.emagsoftware.it/tbosg

Grazie ad entrambi per i chiarimenti.
Ciao.
Antonio

aggiuntive, rispetto ad una semplice funzione.
Ho un dubbio: l'ultimo cout(la chiamata a s.result) dà come risultato
0, mentre dovrebbe, a rigor di logia, dare come risultato 12. Succede
sia con g++ che con VC 6. Perchè? Ho provato a chiamare la funzione
s.result() dall'interno di s.operator(), e lì il risultato è corretto.
Se prima di for chiamo s(100), durante il ciclo for_each tale valore
viene incrementato, ma finito il ciclo, il valore ritorna lo stesso
(cioè 10). Sembrerebbe che il ciclo for_each operi su una copia di
s!!!

 s!!!
Infatti. Eccoti una variante funzionante (ho semplicemente trasformato
res in membro statico):
#include <iostream>
#include <vector>
#include <algorithm>
template < typename T > class Sum
{
    public:
        Sum( T i = 0 ) { res = i; }
        void operator () ( T x ) { res += x; }
        T result() { return res; }
    private:
        static T res;
};
template < typename T > T Sum < T >::res;
int main ()
{
    std::vector < int > c;
    c.push_back( 3 );
    c.push_back( 4 );
    c.push_back( 5 );
    Sum < int > s;
    std::for_each( c.begin(), c.end(), s );
    std::cout << s.result() << '\n';
    return 0;


 res in membro statico):
Io farei cosě (non mi piace usare membri statici in questi casi, rendono il
codice non "rientrante"):
template < typename T > class Sum
{
    T& t_r_;
    public:
        Sum( T & r ) : t_r_(r) { }
        void operator ()( T x ) const { t_r_ += x; }
 };
int main ()
{
    std::vector < int > c;
    c.push_back( 3 );
    c.push_back( 4 );
    c.push_back( 5 );
    int result = 0;
    std::for_each( c.begin(), c.end(), Sum < int >( result ) );
    std::cout << result << '\n';
    return 0;
}
MM

 codice non "rientrante"):
Ottimo! Grazie.
