Newsgroup: it.comp.lang.c++
Titolo: Template e standard.

Ciao a tutto il NG.
Leggendo l'articolo "Programmazione ad Oggetti e Programmazione
Generica" di Carlo Pescio (n° 62 Computer Programming oppure
http://www.eptacom.net/pubblicazioni/pub_it/oopgen.html
), ho trovato
un esempio su un "difetto" del C++, del quale non ho trovato
riscontro "pratico".
Parlando del polimorfismo parametrico Pescio fa questo esempio per
segnalare una possibile fonte di problemi:
template< class T >
T max( const T& a, const T&b )
  {
  if( a < b )
    return( a ) ;
  else
    return( b ) ;
  }
class String
  {
  public :
    String( const char* s ) ;
    operator const char*() const ;
    // ... NON definisco "<"
  } ;
secondo l'articolo in questione il seguente codice (testuali parole)
"compila allegramente":
String s1 = "a" ;
String s2 = "b" ;
String s3 = max( s1, s2 ) ;
Sono ben chiari i problemi che deriverebbero da un comportamento del
genere, pero' se provo a compilare il codice di cui sopra (con VC++
6 e 7) ottengo (giustamente) il seguente errore:
error C2676: binary '<' : 'const String' does not define this
operator or a conversion to a type acceptable to the predefined
operator
Volevo sapere se il restituire un errore o meno in questi casi e'
dipendente dall'implementazione o richiesto dallo standard.
Ciao.

dipendente dall'implementazione o richiesto dallo standard.
Credo che sia un problema (bug?) di VC++ ... anche senza tirare
in ballo i template VC++ 6.0 non compila nemmeno questo codice
  struct X
  {
    operator char * () { return 0; }
  };
  int main()
  {
    X a,b;
    a<b;
    return 0;
  }
mentre la compilazione riesce se al posto di "char *" si usa
ad esempio "int" (questo anche se VC++ 6.0 non ha nessun problema
a usare l'operatore "<" con puntatori a carattere).
Andrea
--
Andrea Griffini, Programmer
http://www.netservers.com/~agriff

 a usare l'operatore "<" con puntatori a carattere).
Questo e' un discorso ben differente.
Ciao.

Questo e' un discorso ben differente.
Hmmm... perche' ?


 
Il gcc compila quindi credo che
  if( a < b )
venga convertito in
  if ( (const char*)a ) < ( ( const char *)b ) )
overo fai il riscontro tra gli indirizzi restituiti dal metodo 
 
  operator const char * ( ) { }
Infatti compilando questo codice ( si lo l'implementazione della classe 
String è errata, ma nel nostro caso .... )
#include <iostream>
using namespace std;
template <typename T>
  T my_max( const T &e1, const T & e2 ){
 
  return e1 < e2 ?  e2 : e1;
 
}
class String
  {
 
    char        *buf;
  public :
    String( const char* s ) { buf=(char*)s;};
    operator const char*() const { return buf; };
    // ... NON definisco "<"
  } ;
 
int main( ){
        String s1 = "b" ;
        String s2 = "a" ;
        String s3 = my_max( s1, s2 ) ;
        cout << s3 << endl;
}
Mi da s2 > s1 indimendentemente dal valore di s2 o s1 ( probabilmente il 
buffer contenente 'a' è allocato dopo a quello di 'b' per cui il suo 
indirizzo è maggiore ....

 a quello di 'b' per cui il suo indirizzo č maggiore ....
Infatti l'articolo esprimeva un parere critico sull'approccio del
C++ in questi casi, affermando che e' causa di potenziali grossi
errori. Se in un codice cosi' semplice gia' le cose non vanno come
ci si aspetterebbe, in caso di codice ben piu' complesso trovare
questi subdoli errori si puo' rivelare un grosso problema.
A questo punto credo il rifiuto di compilare sebbene possa essere un
punto di non attinenza allo standard non lo vedo (mia personalissima
e molto probabilmente errata opinione) come un problema, anzi...
Ciao.

 Hmmm... perche' ?
Questa parte dell'articolo affronta una problematica ben diversa,
non la conversione implicita dei tipi ma proprio cio' che sta alla
base dei template, ovvero il polimorfismo parametrico.
Ciao.

base dei template, ovvero il polimorfismo parametrico.
Io non stavo discutendo sull'articolo: ma solo sul fatto che
quello che hai rilevato sia o meno un bug. Se il compilatore
avesse problemi con le conversioni implicite in genere ti
darei ragione... si tratterebbe cioe' di una (secondo me
molto discutibile) scelta. Non e' pero' questo il caso visto
che altre conversioni implicite sono ammesse "tranquillamente".


 dipendente dall'implementazione o richiesto dallo standard.
Secondo lo standard non c'e' nessun errore.
A mio avviso l'"errore" lo ha fatto il programmatore quando ha definito
"operator const char*" come membro di una classe stringa. Una stringa non e' un
puntatore a carattere. Non e' corretto convertire implicitamente una stringa in
un puntatore a carattere. Al massimo ha senso poter ottenere un puntatore al
buffer gestito internamente dalla classe stringa sotto forma di puntatore a
carattere. Ma questa non e' una conversione. E' un accesso ad un membro interno.
E richiede un metodo, non un operatore di conversione.
--
Andrea Ferro
---------
Brainbench C++ Master. Scored higher than 97% of previous takers
Scores: Overall 4.46, Conceptual 5.0, Problem-Solving 5.0
More info 
http://www.brainbench.com/transcript.jsp?pid=2522556

 che altre conversioni implicite sono ammesse "tranquillamente".
Avevo anche qui frainteso le tue parole (dopo giornate pesanti
spesso ho difficolta' a ricordarmi pure il mio nome ;-))
Ciao.

 puntatore a carattere.
[cut]
Era un esempio per mostrare i possibili problemi causati da un
approccio "filosofico" del C++, e quindi penso volutamente non
corretto.
Ciao.

 Infatti, e cio' e' una limitazione.
Una piccola correzione concettuale: questa *non* e' una limitazione,
anzi la segnalata assenza di una rete di sicurezza lascia aperte
possibilita' in piu'.
Il problema e' che in C++ una stessa espressione puo' essere
implementata da funzioni diverse:
A a;
B b;
C c = a + b;
Puo' essere implementato come:
struct A { C operator+(const B &); };
C operator+(const A&,const B&);
Tralasciando tutte le possibili combinazioni di const, volatile e
reference. Specificare un'interfaccia attraverso le dichiarazioni delle
funzioni supportate sarebbe o troppo faticoso o troppo limitante;
l'alternativa e' aggiungere una nuova notazione, che non mi pare una
scelta attraente neppure questa.
Tutto sommato gli idiomi che si stanno diffondendo per forzare il
controllo del supporto di determinate interfacce da parte degli
argomenti di template mi paiono il male minore.
Ciao,
Nicola

 corretto.
L'approccio filosofico e': "Il programmatore di applicazioni sa meglio
del disegnatore di linguaggi qual'e' il suo scopo, e quindi anche cosa
gli serve per raggiungerlo". A me pare imbattibile.
Si puo' poi discutere su quanto sia efficace la sua realizzazione.
Ciao,
Nicola

 C operator+(const A&,const B&);
Sbaglio o i maggiori problemi del C++ con i template ( sopratutto x quanto 
riguarda le conversioni: costruttore o operatore che siano )  si hanno 
quando si usa l'overloading degli operatori ? Un mio amico mi ha fatto 
notare che il Java rinunciando a questi si è tolto un mucchio di rogne.

 notare che il Java rinunciando a questi si è tolto un mucchio di rogne.
Sono le conversioni implicite che vanno usate con molta cautela. Per il
resto e' come dire che in triciclo ci si puo' far meno male che in
Ferrari: vai a dirlo a Schumacker, pero'.
Ciao,
Nicola

 notare che il Java rinunciando a questi si č tolto un mucchio di rogne.
IMHO il problema e' piu' con le conversioni che con gli operatori. E comunque
deriva non dal loro uso ma dal loro uso scorretto. Ovvio che e' molto piu'
facile usare scorrettamente un operatore o una conversione che non una funzione
membro con nome.


notare che il Java rinunciando a questi si è tolto un mucchio di rogne.
...ma anche un mucchio di possibilità in più. Io preferisco scegliere
se usare i template (ed eventualmente anche le rogne ad essi
collegati) o non usarli, non essere costretto dal linguaggio.
Anto
--
Antonio Cuni, 19 anni, studente
Brainbench C++ Master: 4.6, higher than 98% of all previous test takers.
C Language: 3.32, higher than 79% of all previous test takers.
Guida C/C++ di Programmazione.it: 
http://cpp.programmazione.it

Nicola Musatti wrote:

Si ma considerando che guida anche Barrichello ( e si gira ... :((( )..
Non è un intento polemico del tipo C++ meglio/peggo di Java il mio; è 
individuare le zone in cui programmare in C++ è piu' difficile, e per fare 
questo un buon sistema è quello di sfruttare "l'esperienza" del newsgroup.