Newsgroup: it.comp.lang.c++
Titolo: overloading >> with template classes

 
Vi sarei grato se poteste spiegarmi perché nella funzione main se
l'extractor operator è invocato con un oggetto di tipo istream non viene
rilevato nessun errore;  se, diversamente, l'extractor operator è invocato
con un argomento di tipo ifstream il mio compilatore rileva una ambiguità
(ambiguous access to overloaded function). Non abbiate paura di leggere le
definizioni delle due classi: sono molto semplici (potete provare con il
vostro compilatore: sono conformi allo standard). Come è possibile evitare
l'ambiguità?
 
Sergio
do...@insinet.it
#include <iostream>
#include "_line_pricing.h"
#include "_line_pricing.cc"
void main()
{
 
 _line_pricing< int > x_line( 40000, 50000, 40, 25 );
 
 ifstream in_file( "pricing" );
 
 in_file >> x_line;  // cin >> x_line is ok
 
}
   /* abstract class of pricing representation */
   class _a_pricing {
 
     public:
 
      /* it displays the pricing traits */
      virtual void display() const = 0;
 
    };
   #pragma once
 
   #include "_a_pricing.h"
 
   /* class of pricing representation */
   template< class currency >
   class _line_pricing : public _a_pricing {
 
      /* extraction poerator */
      friend ostream& operator << ( ostream &os, const _line_pricing<
currency > &pricing );
      /* insertion poerator */
      friend istream& operator >> ( istream &is, _line_pricing< currency >
&pricing ); 
 
     public:
 
      /* constructors */
      _line_pricing( currency advance = currency(), currency price =
currency(), int child_discount = 0, int teen_discount = 0 );
 
      /* it displays the pricing traits */
      void display() const;
 
     private:
 
      /* pricing */
      currency _price;
      /* advance's representation */
      currency _advance;
 
      /*child's discount representation  */
      int _child_discount;
      /*teen's discount representation  */
      int _teen_discount;
 
    };
 
 
   #include "_line_pricing.h"
 
   /* insertion operator */
 
   template< class currency >
 
   ostream&
   operator << ( ostream &os, const _line_pricing< currency > &pricing )
   {
    os  << pricing._price
     << " "
     << pricing._advance
     << " "
     << pricing._child_discount
     << " "
     << pricing._teen_discount
     << endl;
 
 
    return os;
   }
 
 
   /* extraction operator */
 
   template< class currency >
 
   istream&
   operator >> ( istream &is, _line_pricing< currency > &pricing )
   {
    is  >> pricing._price
     >> pricing._advance
     >> pricing._child_discount
     >> pricing._teen_discount;
 
 
    return is;
   }
 
   /* constructor */
 
   template< class currency >
 
   _line_pricing< currency >::_line_pricing( currency advance, currency
price, int child_discount, int teen_discount ) :
   _advance( advance ),
   _price( price ),
   _child_discount( child_discount ),
   _teen_discount( teen_discount )
   {
 
   }
 
   /* it displays the pricing traits */
 
   template< class currency >
 
   void
   _line_pricing< currency >::display() const
   {
    cout  << "price per person is: "
      << _price
      << endl
      << "the advance is : "
      << _advance
      << endl;
 
   }

l'ambiguità?
Il tuo codice e` *quasi* conforme allo standard.  Per renderlo pienamente
conforme occorre:
-- aggiungere "#include <fstream>", poiche` il solo <iostream>, a norma
    di standard, non rende nota la classe std::ifstream;
-- aggiungere "using namespace std;", poiche`, ancora a norma di
    standard, tutti gli identificatori standard che usi sono, appunto,
    nel namespace std;
-- cambiare il "void main" in "int main" (non e`, a rigor di standard,
    necessario fare esplicitamente un "return 0;" alla fine, poiche`
    esso e` implicito, ma, che io sappia, nessun compilatore offre
    ancora questa comodita`, quindi, io, il "return 0;" lo metterei).
    "void main" causa "undefined behaviour", cioe`: qualsiasi cosa
    succeda compilando o eseguendo questo programma, comprese
    riformattazioni del disco fisso, email minatorie al tuo capo, ecc
    ecc, il compilatore che risponde alla vista di "void main" causandole,
    e` PERFETTAMENTE aderente allo standard (in questo, il C++ e`
    identico al C).
Nessuna di queste deviazioni (tutte, immagino, suggerite da modi
in cui il tuo compilatore si discosta dallo standard) presumibilmente
spiega la "pseudo-ambiguita`" che il tuo compilatore diagnostica,
quindi l'ipotesi piu` ragionevole e` che tu abbia teste` scoperto un
bug nel tuo compilatore.  Come aggirare questo bug, mah; la cosa
piu` ragionevole sarebbe anzitutto accertarti di stare usando il
release piu` recente del tuo compilatore preferito, qualsiasi esso
sia, e, se questo bug persiste, provare magari a cambiare la marca
di compilatore; alternativamente, uno "prova un po' di tutto", sinche`
miracolosamente (se e` fortunato) non incappa su di un costrutto
che fa quel che desidera senza solleticare il bug stesso (meglio
evidenziare chiaramente la ragione per costrutti strani, di aggirare
bug nei compilatori, indicando di che release si tratta; e porli sotto
#if/#else, per facilita` nel rimuoverli quando in futuro si avra` a
disposizione un compilatore migliore).  In passato ho fatto molti
porting fra compilatori diversi, specie i vari C++ proprietari di HP,
IBM, Dec, Silicon, ecc, per i rispettivi Unix, e bug del genere non
mi stupivano piu`, se ne trovavano due al giorno...!
Alex