Newsgroup: it.comp.lang.c++
Titolo: Warning ottenuto creando una funzione template

Ho creato una piccola funzione template per stampare un vector
su uno stream:
#include <iostream>
#include <vector>
using namespace std;
template <class T>
ostream& StampaVettore(vector<T> vect, ostream& str = cout) {
    for(vector<T>::iterator iter = vect.begin(); iter != vect.end(); ++iter)
{
        str << *iter << endl;
    }
    return str;
}
Il codice compila, ma mi arriva questo warning dal gcc:
8: warning: `typename std::vector<T, std::allocator<_CharT> >::iterator' is
implicitly a typename
qualcuno mi sa spiegare cos'è un typename?
tia
--
Lupin85©
Azzurranet IRC: +#afiad, @#fils - ICQ: 91528290
Mail: Remove PAN to contact me
- "It is not important what you believe, only that you believe." -

 qualcuno mi sa spiegare cos'è un typename?
Non molto bene, è un qualcosa definito con un typedef (credo). Per togliere 
il warning fai così:
template <class T>
ostream& StampaVettore(vector<T>& vect, ostream& str = cout)    
// Meglio prendere reference ad un vettore
{
        for (typename vector<T>::iterator iter = vect.begin(); iter != vect.
end(); ++iter) {
                str << *iter << endl;
        }
        return str;
}
Poi, perchè restituisci un ostream&? Mica vorrai fare qualcosa tipo:
StampaVettore (v, cout) << "Ciao" << endl;
Sarebbero orribili :-) Io la preferirei così:
template <tpename Container>
void StampaVettore(Container& c, ostream& str = os) 
{
        for (typename Container::iterator iter = c.begin(); iter != c.
end(); ++iter)
                os << *iter << endl;
}
Usando Container al posto di vector<T> hai più flessibilità, in quanto puoi 
passare anche liste eccetera. Anche se per un funzione StampaVettore non è 
molto utile :-) Ciao.
-- 
Andrea Bergia - studente          Linux Registred User #281550
Per favore non mandatemi allegati in Word o PowerPoint.
Si veda 
http://www.fsf.org/philosophy/no-word-attachments.html

 molto utile :-) Ciao.
Bè, in effetti la tua è più generale e meglio si adatta all'idea di template
:)
ma a me serve solamente per stampare vettori (per ora), per cui mi
accontenterò
della mia :)
grazie mille per il chiarimento sul typename (anche se sono ancora un po'
confuso)


 - "It is not important what you believe, only that you believe." -
Saluti
Rosario Ianuale
P.s.: spero di non essere stato troppo oscuro. Ho preso l'esempio dal libro
per non scrivere sciocchezze e poi perchè sono le 4.00 di mattina... e sono
abbastanza assonnato.

 qualcuno mi sa spiegare cos'è un typename?
la questione non e` semplicissima...
partiamo dall'inizio: quando il compilatore deve compilare un sorgente 
prima di tutto ne fa il parsing: il parser prende il sorgente e lo 
elabora in modo da avere una struttura facile da analizzare 
successivamente; purtroppo la sintassi del C (e di conseguenza del C++) 
e` semi-ambigua e ci sono dei casi in cui il parser e` un po' in 
difficolta`; considera ad esempio questo:
int x = 0;
// typedef int foo // per ora ignora questo typedef
void foo(int);
void bar()
{
        foo(x);
}
A prima vista sembra tutto semplice: bar() richiama foo() utilizzando 
come parametro la variabile globale x. Ora prova a decommentare il 
typedef e a commentare la "void foo(int)"; quando il compilatore 
incontra la riga "foo(x)" la "vede" come se fosse:
        int (x);
in questo caso le parentesi sono considerate superflue e quindi la riga 
incriminata ha l'effetto di *definire una variabile locale x di tipo 
int*. Come puoi vedere la *stessa* riga e` interpretata in modo 
completamente diverso a seconda se foo e` un tipo o una funzione.
Sino a che scriviamo codice "normale" non si pone il problema, dato che 
il compilatore sa sempre se un nome e` riferito ad un tipo o una 
funzione e quinidi sa anche come interpretare le ambiguita`. Ma 
considera il template:
template<class T>
void bar()
{
        T::foo (x);
}
come fa il compilatore a sapere se T::foo e` un tipo o (ad esempio) una 
funzione statica? Non lo puo` sapere fino a che non si istanzia il 
template, ma il parser deve saperlo *prima*, al momento di analizzare il 
sorgente; il comitato di standardizzazione ha deciso che se ci si deve 
riferire ad un tipo definito in una classe parametro di template si deve 
usare la keyword "typename"; quindi se ci aspettiamo che T::foo sia un 
tipo dobbiamo scrivere:
template<class T>
void bar()
{
        typename T::foo (x); // le parentesi sono superflue
}
Il tuo caso e` esattamente analogo a questo: il compilatore non puo` 
sapere cosa sia vector<T>::iterator sino a che non istanzia il template, 
quindi devi usare typename per risolvere l'ambiguita`. Poi succede che 
il g++ e` particolarmente intelligente e riesce a capire lo stesso cosa 
vuoi fare, pero` ti informa che a norma di standard dovresti mettere 
typename.
Per la cronaca la tua funzione StampaVettore si puo` scrivere anche 
prendendo spunto da questo:
#include <vector>
#include <iterator>
#include <iostream>
#include <algorithm>
int main()
{
  std::vector<int> v;
  v.push_back(3);
  v.push_back(6);
  v.push_back(9);
  std::copy(v.begin(), v.end(), 
                std::ostream_iterator<int>(std::cout, "\n"));
}
ciao Anto
-- 
"Computer science is not about computers any more than astronomy
is about telescopes." -- EW Dijkstra

 }
Ergo, ho reinventato la ruota.
Giusto?
--
Lupin85©
Azzurranet IRC: @#afiad, @#fils, @#pokegalaxy - ICQ: 91528290


 Giusto?
beh, a voler essere pignoli si, pero` quel che conta e` che tu abbia 
imparato qualcosa: se ti metti a scrivere una libreria e questa non e` 
ultra-innovativa e` probabile che qualcun'altro abbia gia` fatto 
qualcosa si simile: ma se dallo sviluppo di questa libreria riesci a 
imparare qualcosa il tempo non e` buttato via, anzi!
In questo caso tra le altre cose hai anche imparato qualcosa sugli 
iteratori di input/output, no?
