Newsgroup: it.comp.lang.c++
Titolo: Aiuto: default arguments in funzioni template!

Salve,
perchè questo:
template<typename T>
void test(int v1, int v2 = 0) {
  ...etc...
}
int main () {
   test(0);
}
non viene compilato? GCC da l'errore: "error: no matching function for 
call 'test(int)'.
Grazie 1000!

 call 'test(int)'.
Giustamente, per inciso. Suggerisco di ridare una breve lettura alla
scrittura di funzioni templatiche.
Hint: come può inferire T?
Hint2: a che serve avere dipendenza da un T che non usi mai?
Hint3: come dichiari un'istanza di un tipo templatico? perchè e quando
puoi fare diversamente quando hai a che fare con una funzione
templatica?
-- 
-riko

 Hint2: a che serve avere dipendenza da un T che non usi mai?
non ho incluso quelllo che c'era dentro la funzione.
Ringrazio per la pazienza!

 }
Devi invocarla cosi:
test<int, int>(0);
Ciao 

 
Perchè non deduce da solo il tipo del secondo argomento? E' corretto e 
nello standard C++ questo comportamento?
La funzione template in questione dovrebbe essere usata da altri, e mi 
sembrerebbe un po' brutto dover far specificare il tipo di argomenti non 
  passati.

 nello standard C++ questo comportamento?
T1 e T2 sono parametri template, quindi si attende dei tipi, come int.
Non puoi passare i soli parametri di funzione, sperando che vengano 
utilizzati per dedurre il tipo dei parametri template. 

 non avviene?
Non conosco lo standard, ma puoi risolvere il tuo problema con il 
seguente codice:
template<typename T1, typename T2>
void test(T1 v1, T2 v2)
{
	// Body
}
template<typename T1>
void test(T1 v1)
{
	return test(v1, 0);
}
-- 
     Carlo Milanesi
 
http://digilander.libero.it/carlmila

 }
Immagino ch in alcuni casi, abbia necessità di specificare anche il secondo 
parametro. Se non dovesse mai farlo, invece che metterlo di default 
l'avrebbe tolto. 

Noixe ha scritto:

E chi glielo impedisce?
Il seguente programma:
   #include <iostream>
   template<typename T1, typename T2>
   void test(T1 v1, T2 v2)
   {
     std::cout << v1 << v2 << std::endl;
   }
   template<typename T1>
   void test(T1 v1)
   {
     return test(v1, 0);
   }
   int main () {
     test("abc");
     test("def", "ghi");
   }
ha il seguente output:
abc0
defghi


 utilizzati per dedurre il tipo dei parametri template. 
perchè no? In questo case scrivere
test<int,int>(10,20);
ha lo stesso effetto di:
test(10,20);

 
E' la soluzione che ho adottato finora. Però mi chiedevo perchè non 
fosse possibile sfruttare il parametro di default.

 fosse possibile sfruttare il parametro di default.
Ho trovato questa documentazione (cerca "default argument." nella pagina):
http://publib.boulder.ibm.com/infocenter/macxhelp/v6v81/index.jsp?topic=/com.ibm.vacpp6m.doc/language/ref/clrc16deducing_type_templ_param.htm
Qui asserisce che la sintassi che proponi tu non e' ammessa.
D'altra parte la mia soluzione richiede solo 5 righe in piu' (o volendo 
una sola!) e quindi la situazione non e' drammatica.


 io mi riferisco al parametro di default: questo č un int per default.
No. Quello e' 0 per default. 0 e' un valore valido anche per
inizializzare un puntatore. Scritto proprio 0.
Il compilatore come fa a capire se vuoi che sia un puntatore o meno?
Infatti come fai notare usando un valore diverso da 0, sei a posto.
Occhio a queste cose, meglio scrivere codice piů esplicito IMHO che
lasciare indeterminatezza...
-- 
-riko

 Infatti come fai notare usando un valore diverso da 0, sei a posto.
Usando un valore diverso da zero (..1..etc..) non cambia nulla: lo 
stesso vale per qualsiasi altro tipo, anche dove non c'è possibilità di 
ambiguità.
Ci sarà un valido motivo, ma sembra non si possano specificare parametri 
di default nelle funzioni template ed aspettarsi che i loro tipi vengano 
usati per dedurre il tipo.
Vedi dal link di Carlo Milanesi:  "The compiler cannot deduce a template 
argument from the type of a default argument."

 test(10,20);
Ma ha effetto secondo te, perché
template <typename T>
void test(int v1, int v2 = 0) {};
int main () {
    test(10, 20);
}
Non compila 

 E chi glielo impedisce?
Si vero, quella era solo una specializzazione, c'č anche la versione che 
accetta due parametri :-) 

 ambiguità.
Come valore di default certo. Io parlavo di quelli passati nel
call-site. I parametri di default semplicemente non partecipano nel
processo di inferenza del tipo.
Infatti il codice come lo hai scritto non dovrebbe essere scritto.
Quello 0 limita *troppo* l'applicabilita' della funzione (in modo non
necessario).
Il modo corretto di scrivere *dovrebbe* essere questo:
template<typename T1, typename T2 = int>
    void test2(T1 v1, T2 v2 = T2())
{
}
Peccato che per reminiscenze del vecchio C++ non sia possibile neppure
questo (ovvero specificare il default per i tipi delle funzioni
templatiche).
In effetti il giochetto con le classi templatiche funziona:
template<typename T1, typename T2 = int>
class Test {
    public:
    void operator()(T1 v1, T2 v2 = T2()) {}
};
Test<int> test3;
int main () {
//   test(2);
    test3(2);
}
Peccato che poi non ti fa piu' inferenza sul primo parametro. In
definitiva io scriverei il codice diversamente e amen.
-- 
-riko

 processo di inferenza del tipo.
...era questo il problema. Vabbè basta saperlo!