Visualizzazione dei risultati da 1 a 3 su 3
  1. #1

    [C++] Template e funzioni friend

    Ciao a tutti, sto leggendo una guida sul C++ e sono arrivato ai template. Per fare una prova, ho fatto questa classe:

    codice:
    template <int _N> class Zn
    {
        int _val;
        int _mod(int n){ return (n>=0) ? (n % _N) : (_N - ( (-n) % _N))%_N; }
    
        public:
            Zn(){ _val = 0; }
            Zn(int n){ _val = _mod(n); }
            Zn operator +(Zn b){ return Zn(_val + b._val); }
            Zn operator -(Zn b);
            int getN(){ return _N; }
            int getval(){ return _val; }
    };
    
    template <int _N> Zn<_N> Zn<_N>::operator -(Zn<_N> b)
    {
        return Zn(_val - b._val);
    }
    dove ho scritto il + in modo inline, e il - in modo espanso (tutto corretto?)
    Ora, volevo aggiungere il << per stampare a video, ma dovendo fare una funzione friend, non ho idea della sintassi (che sul libro non c'è scritta in questo caso specifico).
    Quello che avevo pensato "inventando a senso" era:

    codice:
    template <int _N> class Zn
    {
        int _val;
        int _mod(int n){ return (n>=0) ? (n % _N) : (_N - ( (-n) % _N))%_N; }
    
        public:
            Zn(){ _val = 0; }
            Zn(int n){ _val = _mod(n); }
            Zn operator +(Zn b){ return Zn(_val + b._val); }
            Zn operator -(Zn b);
            int getN(){ return _N; }
            int getval(){ return _val; }
    
            template <int _N> friend ostream &operator <<(ostream &stream, Zn<_N> o);
    };
    
    template <int _N> Zn<_N> Zn<_N>::operator -(Zn<_N> b)
    {
        return Zn(_val - b._val);
    }
    
    template <int _N> ostream &operator <<(ostream &stream, Zn<_N> o)
    {
        stream << o._val;
        return stream;
    }
    che però non compila, sembra che il <int _N> nel caso di una funzione membro viene preso quello della classe, nel caso di una funzione non membro viene "ridefinito", e infatti il compilatore mi segnala una duplicazione di _N... e allora ho modificato così:

    codice:
    template <int _N> class Zn
    {
        int _val;
        int _mod(int n){ return (n>=0) ? (n % _N) : (_N - ( (-n) % _N))%_N; }
    
        public:
            Zn(){ _val = 0; }
            Zn(int n){ _val = _mod(n); }
            Zn operator +(Zn b){ return Zn(_val + b._val); }
            Zn operator -(Zn b);
            int getN(){ return _N; }
            int getval(){ return _val; }
    
            template <int __N> friend ostream &operator <<(ostream &stream, Zn<__N> o);
    };
    
    template <int _N> Zn<_N> Zn<_N>::operator -(Zn<_N> b)
    {
        return Zn(_val - b._val);
    }
    
    template <int __N> ostream &operator <<(ostream &stream, Zn<__N> o)
    {
        stream << o._val;
        return stream;
    }
    e così funziona tutto. Ho inoltre anche aggiunto il + tra due classi diverse, facendo:
    codice:
    #include <iostream>
    
    
    using namespace std;
    
    template <int _N> class Zn
    {
        int _val;
        int _mod(int n){ return (n>=0) ? (n % _N) : (_N - ( (-n) % _N))%_N; }
    
        public:
            Zn(){ _val = 0; }
            Zn(int n){ _val = _mod(n); }
            Zn operator +(Zn b){ return Zn(_val + b._val); }
            Zn operator -(Zn b);
            int getN(){ return _N; }
            int getval(){ return _val; }
    
            template <int __N> friend ostream &operator <<(ostream &stream, Zn<__N> o);
    
            template <int __N1, int __N2> friend Zn<__N1> operator +(Zn<__N1> o1, Zn<__N2> o2);
    };
    
    template <int _N> Zn<_N> Zn<_N>::operator -(Zn<_N> b)
    {
        return Zn(_val - b._val);
    }
    
    template <int __N> ostream &operator <<(ostream &stream, Zn<__N> o)
    {
        stream << o._val;
        return stream;
    }
    
    template <int __N1, int __N2> Zn<__N1> operator +(Zn<__N1> o1, Zn<__N2> o2)
    {
        return Zn<__N1>(o1._val + o2._val);
    }
    e anche questa cosa funziona.

    La mia domanda è: è giusto quello che ho scritto, visto che l'ho "inventato"? C'è un modo migliore?

    Grazie!

  2. #2
    Nessuno mi sa dare una mano?
    grazie

  3. #3
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Il codice che dici che non compila, (il secondo listato) a me compila bene con VC++2010. Però essendo un compilatore moderno, con parziale supporto al C++0x, può non avere i problemi che riscontri tu.
    Detto questo.
    Da un punto di vista pratico, io eviterei di impasticciarmi con funzioni friend dichiarate / definite all'esterno della classe (se non come in questo caso per mero studio), specie in presenza di template.
    In genere si definiscono direttamente nel corpo della classe: è più pratico e meno incasinato.

    La teoria comunque vorrebbe un codice simile:
    codice:
    template <int _N> class Zn; // forward declaration.
    
    template <int _N>
    ostream& operator << (ostream&, const Zn<_N>& ) ; // forward declaration della funzione friend.
    // Notare che richiede almeno un reference.
    
    template <int _N> class Zn
    {
     ...
    
            friend ostream &operator << <_N>(ostream &stream, const Zn& o ) ;
    };
    // definizione della funzione.
    template <int _N> ostream &operator <<(ostream &stream, const Zn<_N>& o)
    {
        stream << o._val;
        return stream;
    }
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.