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

Salve gente,
questito: non riesco a capire cosa mi sta dicendo il compilatore.
Ho scritto un template per gestire array bidimensionali ( nel senso di
geometrico R^2 ), ed ora sto implementando i metodi per le operazioni;
mi sono bloccato al metodo che mi permette di moltiplicare un vettore
per uno scalare ( non ancora il contrario con funzione friend ).
La dichiarazione e' la seguente:
template < typename Real, typename Scalar >
		Vector2< Real > operator*( const Scalar & S );
la definizione invece e' :
// Vettore v * uno scalare qualsiasi
template < typename Real, typename Scalar >
		Vector2< Real > Vector2< Real >::operator*( const Scalar & S )
{
	Vector2< Real > Sum;
 
	Sum.SetX( _components[ 0 ] * S );
	Sum.SetY( _components[ 1 ] * S );
 
	return Sum;
 
}
N.b.: ho separato definizione e dichiarazione mettendo la prima in un
file .impl incluso dalla classe, giusto per non avere una marea di
codice entro cui guardare in caso di errore.
Se provo ad utilizzare questo codice il compilatore mi dice:
error C2244: "operator`*'": impossibile trovare una corrispondenza tra
la definizione della funzione e una dichiarazione esistente
        definizione
        "Vector2<Real> Vector2<Real>::operator *(const T2 &)"
        dichiarazioni esistenti
        "Vector2<Real> Vector2<Real>::operator *(const Scalar &)"
In particolare non riesco a capire quello che lui chiama T2 ed io ho
chiamato Scalar, non credo sia un problema di aliasing ma qualcosa di
piu' *fico*, tipico di quei simpaticoni dei template.
Grazie per le risposte,
   BR

Giusto per la cronaca aggiungo che il compilatore e' il VC++ 7, grazie.

    Vector2< Real > operator*( const Scalar & S );
Questa dichiarazione è dentro la definizione della Vector2<T>? 
Se è così, trattandosi di funzione template in una classe template, nella 
sua definizione dovranno figurare due keyword template. Mi fa specie, però 
che tale dichiarazione parametrizzi anche il tipo di ritorno, che dovrebbe 
essere lo stesso della classe, non uno generico. Magari mi sbaglio, ma 
secondo me tu volevi scrivere:
 template < typename Real >
 class Vector2 
 {
   ...
   template < typename Scalar >
       Vector2< Real > operator*( const Scalar & S );
   ...  
  }
Nel qual caso, la definizione sarà:
   template < typename Real >
    template < typename Scalar >
      Vector2< Real > 
      Vector2< Real >::operator*( const Scalar & S ) 
       { 
          // etc...
Max

Max M. ha scritto:

Preciso, avevo creato tra l'altro anche casini con il copia ed incolla.
Adesso l'operatore funzione membro che mi permette di fare
vett x scalare
funziona.
Adesso pero' non riesco a definire l'operatore che mi consenta di fare
scalare * v.
Dovrebbe essere friend, per cui dovrei dichiararlo come:
template< Scalar > friend Vector< Real > operator*( const Scalar & S );
giusto ??
Non riesco a valutare l'implementazione perchè il compilatore mi da un
errore abbastanza inquietante:
fatal error C1001: ERRORE INTERNO DEL COMPILATORE
Nn capisco che succede.

 giusto ??
No. Innanzitutto, se è una funzione ordinaria (cioè, non è una funzione 
membro), dovrà avere due argomenti: lo Scalar e il Vector2<Real>. A 
differenza dell'altra, questa dovra essere parametrizzata sia su Real che 
su Scalar. Quindi:
Dichiarazione friend all'interno della definizione di Vector2:
 template< typename Real > 
 class Vector2
 {
  template< typename Scalar > 
   friend Vector2<Real> operator*<Scalar,Real> ( // <-- nota questo punto!!!
                    const Scalar & S, const Vector2<Real>&);
 }; 
Definizione:
 template< typename Scalar, typename Real > 
  Vector2<Real> operator*(const Scalar & S, const Vector2<Real>& )  
 { ...
 
Non mi pare, comunque, sia necessario rendere friend tale funzione, giacché 
puoi implementarla invocando l'altro operator* (il quale, per inciso, 
andrebbe dichiarato 'const').
Max

Max M. ha scritto:
[ cut ]
Ciao,
i tuoi consigli hanno funzionato fino alla funzione friend, che ho
dovuto correggere. Adesso vorrei sapere se quelle correzioni sono
dettate dallo standard o se magari sono dovute ad un disallineamento del
compilatore [ VC++ 7 ]:
La dichiarazione:
template< typename Scalar, Real >
friend Vector2<Real> operator*< Scalar, Real > // Devo specificare real
& scalar
( const Scalar & S, const Vector2<Real> & V);
mentre la definizione diventa:
template< typename Scalar, typename Real >  // Devo definire anche Real!
Vector2<Real> operator*( const Scalar & S, const Vector2<Real>& V )
Che ne pensi ??
Grazie ancora,
   B

 compilatore [ VC++ 7 ]
Boh. :)
Di certo la mia dichiarazione non va bene. (Chiedo venia. Effettivamente 
non uso mai funzioni friend: non sono mai indispensabili.) 
Ti suggerisco di produrre una versione minimale, darla in pasto al Comeau 
online (
http://www.comeaucomputing.com/pcgi-bin/compiler.cgi
), e vedere un 
po' che ti dice. Questo compilatore č ritenuto perfettamente (o quasi) 
aderente allo Standard.
Max

 aderente allo Standard.
Interessante sta cosa del comeau, anch'io sapevo della quasi aderenza
allo standard.
Per quanto riguarda la funzione
n * v
in che senso non la dichiari friend ??
Nel senso che la dichiari esterna alla classe come una funzione
qualunque ? Avendo i metodi di 'set' per recuperare le info che servono
dalla classe effettivamente si puo' fare....
La intendi cosi' ?
Ciao !

 dalla classe effettivamente si puo' fare....
Metto l'implementazione in una funzione membro pubblica e invoco
quest'ultima dalla funzione ordinaria, la quale non ha più bisogno di
essere friend.
Nel tuo caso, non ti basta invocare l'altro operator*?
Max