Newsgroup: it.comp.lang.c++
Titolo: varargs e reference a oggetti non pod

C'e' un modo per passare ad un metodo che accetta un numero variabile di 
parametri con la sintassi varargs (...) dei reference a oggetti di tipo 
non POD? Ecco un esempio che ovviamente non funziona...
#include <iostream>
#include <stdarg.h>
#include <string>
struct Pippo
{
     Pippo(const std::string &t) : s(t) {}
     std::string s;
};
int pippo(int num, ...) {
     va_list va;
     va_start(va, num);
     while (num--) {
         const Pippo &p = va_arg(va, const Pippo &);
         std::cerr << p.s;
     }
     va_end(va);
}
int main()
{
     Pippo hello("hello");
     pippo(2, Pippo("Ciao!"), hello);
}

 POD? Ecco un esempio che ovviamente non funziona...
Se ben ricordo è affar tuo gestire i parametri aggiuntivi. Puoi 
metterci e farci quel che vuoi.
Il primo esempio che mi è capitato con google
http://msdn2.microsoft.com/en-us/library/kb57fad8(VS.80).aspx
e vedi che per usare va_arg devi sapere il tipo.
Non voglia di andarmi a leggere la documentazione per darti una 
risposta puntuale. Per ti consiglio di farlo, si dovrebbe potere fare.
+++
Volendo sfrucugliare una funzione "generica" la farei così:
int pippo(qualcosa formattazione, ...);
che per non inventarsi la ruota diventerebbe:
int pippo(const char * formattazione, ...);
+++
Volendo sfrucugliare versione 2, sei "sicuro-sicuro" di fare questo? 
Queste funzioni sono difficili da maneggiare se ci sono crash, ovvero 
può capitare che la funzione sbagliata sia "qui" ma tu vedi un crash 
"là".
-- 
Articolo 33 della Costituzione italiana: L'arte e la scienza sono 
libere e libero ne è l'insegnamento

 non POD? 
Direi che non è possibile, perché quando chiami la funzione il 
compilatore non può sapere che vuoi passare i riferimenti, e cerca 
invece di passare gli oggetti per valore. Perchè non passi i puntatori?
E.

 invece di passare gli oggetti per valore. Perchč non passi i puntatori?
Perche` e` fondamentale che i parametri possano essere degli oggetti 
temporanei creati inline.
In ogni modo anche il dover specificare il numero di parametri o dover 
aggiungere un tappo (NULL o simili) alla fine dei parametri e` una 
limitazione troppo grossa. Penso che usero` una serie di chiamate in 
overload con da 1 a X parametri (con X intorno ai 10). Ho visto che 
anche diverse librerie di boost fanno cosi`, con un po` di magia 
aggiuntiva del preprocessor per evitare di scrivere X volte il metodo.
Bye,
  Gabry

 temporanei creati inline.
Ma è comunque sbagliato passare un riferimento ad un oggetto temporaneo!
E.

 limitazione troppo grossa.
Secondo me dovresti riguardarti come funziona l'overloading 
dell'operatore << nella cout. Secondo me fa quello che vuoi.


 tipo non POD? Ecco un esempio che ovviamente non funziona...
Ti indico una soluzione alternativa...
un qualche contenitore di boost::any?
IMHO Potrebbe funzionare.
-- 
I know of a particular, very large software producer that explicitly 
assumes that design takes 20% of developers' time, and debugging takes 
80%.
Niklaus Wirth

 Ma è comunque sbagliato passare un riferimento ad un oggetto temporaneo!
Se il riferimento e` const no, perlomeno il linguaggio permette da 
sempre di utilizzare il temporaneo come parametro (le vecchie versioni 
del VC lo permettevano anche sui non const... brrr).
Comunque esplicito quello che sto facendo x una migliore comprensione.
Sto scrivendo un wrapper C++ sperimentale delle librerie GTK. I 
requisiti che mi son posto e` che sia composto di soli header, che usi i 
puntatori il meno possibile, che abbia un sistema di bind delle callback 
all'interno di classi C++ arbitrarie piuttosto flessibile e che permetta 
operazioni molto intuitive x creare le varie gui.
Al momento un dialog con un bottone e una label di testo lo posso creare 
cosi` (sorvolando sul fatto che esiste pure una classe Dialog che fa 
qualcosa di simile):
#include "oogtk.h"
using namespace gtk;
class MyApp : Application {
	Window m_win;
public:
	MyApp() : m_win("Test") {
		StockButton button(GTK_STOCK_OK);
		VBox box(Label("Hello world!"), VSeparator(), button);		
		box.Border(16); box.Spacing(8);
		button.OnClick(&Application::Quit,
			       dynamic_cast<Application *>(this));
		m_win.Child(box);
		m_win.ShowAll();
	}	
}
int main()
{
	MyApp app;
	app.Run();
}
Gli oggetti "wrapper" intermedi (label, box, stockbutton, separator), 
esistono solo nello scope del costruttutore, poi scompaiono, ma tramite 
il sistema di reference di GTK in quanto i widget sono legati ad un 
padre acquistano un altro reference che li mantiene in vita fino a 
quando la finestra (m_win), non viene distrutta.
Come vedi l'oggetto vbox accetta come parametro il riferimento al 
wrapper dei suoi figli, per fare cio` ho dovuto creare N costruttori a 
seconda del numero di widget (oltre a quello standard con GTK che ha 
altre tipologie di parametri), ovviamente c'e' la possibilta` di 
aggiungere/rimuovere child dopo la costruzione dell'oggetto, ma vorrei 
facilitare la scrittura dell'interfaccia al massimo in modo da rendere 
la scrittura della gui "inline" piu` semplice e leggibile.
Al momento il progetto sta crescendo per supportare un'applicazione che 
sto scrivendo x l'azienda x cui lavoro, ma la libreria rimarra` 
opensource e spero avra`, quando raggiungera` l'usabilita`, contributi 
esterni. Di sicuro ci lavorero` sopra fino a quando non avra` tutte le 
feature necessaria per questa e le prossime applicazioni GUI che dovro` 
scrivere, e spero di riuscire ad introdurre all'uso di questo wrapper 
anche qualche collega.
Al momento l'alpha e` gia` su sourceforge 
(
http://sf.net/projects/oogtk
), ovviamente c'e' solo l'SVN attivo e la 
documentazione presente sono solo i numerosi commenti nei 7 o 8 esempi, 
il piu` complesso dei quali e` il classico text-editor. Le API comunque 
si mantengono filosificamente vicine a quelle di GTK cercando di 
eliminare le cose superflue e, quando possibile, fornire versioni che 
fanno uso di concetti tipici dell'STL (ad esempio gli iteratori dei 
TextBuffer sono gestibili come se fossero gli iteratori di una stringa).
Ovviamente prima di iniziare a scrivere sta "cosa" ho usato per MOLTI 
anni GTK in decine di applicazioni e ho anche provato a usare 
l'estensione "ufficiale" c++ gtkmm che pero` non mi e` mai piaciuta 
particolarmente.

 dell'operatore << nella cout. Secondo me fa quello che vuoi.
La cosa e' interessante, stavo pensando se puo` valer la pena ridefinire 
l'operatore << per tutti gli oggetti di tipo container e permettere una 
sintassi di questo tipo:
VBox cont;
cont << child1 << child2;
... magari aggiungendo anche qualcosa tipo gli iostream manipulators per 
decidere le proprieta` dell'oggetto successivo.

 del VC lo permettevano anche sui non const... brrr).
Stiamo parlando ad esempio di:
class T {
};
void f(const T &);
void g() {
	f( T() );
};
Mi pare molto strano che questo possa essere codice corretto. Come fa il 
compilatore a sapere quando può distruggere la variabile creata con T()?
E.

 wrote :

Quando esce dallo scope, ossia quando la funzione f ritorna.
- gio

 l'operatore << per tutti gli oggetti di tipo container
Questo lo sai solo tu. Se ti piace questo stile di codifica, usalo. Con 
l'esperienza e il tempo scoprirai se era una scelta buona o meno. Se 
non fai non sai, o qualcosa del genere, il proverbio esatto non me lo 
ricordo.
