Newsgroup: it.comp.lang.c++
Titolo: Variabili globali eliminate

Ciao a tutti.
Ho un problema che non riesco a risolvere se non con soluzioni molto 
scomode e poco eleganti; magari e' una FAQ, ma non riesco a trovare 
nulla in merito.
Ho un codice tipo il seguente (so che non e' completo, ne' compilabile, 
ma dovrebbe rendere l'idea):
template <...> class A {...};
A<...> B(...);
La costruzione di B ha degli effetti per me necessari (aggiorna altri 
oggetti globali), ma se non uso B da nessuna parte, il compilatore (o il 
linker) non lo includono nell'eseguibile, il costruttore di B non viene 
chiamato e tutto quanto non funziona.
Se da qualche parte metto:
A<...>&Dummy=B;
si risolve, ma preferirei evitare.
C'e' qualche soluzione? Anche solo un link a della documentazione in 
merito mi farebbe molto comodo.
Succede sia con g++ che con VC8.
  bye & Thanks
	av.


Al di là del fatto che con GCC a me viene correttamente incluso nei
simboli:
// -----------------------
template<typename T>
class A
{
public:
        A (const T& a) : _a (a) {};
private:
        T _a;
};
A<int> b(5);
// -----------------------
matteo@Tulip:~$ g++ -c pippo.cc
matteo@Tulip:~$ nm -C pippo.o
0000003b t global constructors keyed to b
0000000a t __static_initialization_and_destruction_0(int, int)
00000000 W A<int>::A(int const&)
         U __gxx_personality_v0
00000000 B b                          <<<<<<<< QUI <<<<<<<<
00000000 T main
Comunque sarebbe di gran lunga meglio se usassi il pattern Singleton,
che risolve tutti i tuoi problemi in modo molto più elegante.
http://en.wikipedia.org/wiki/Singleton_pattern
Ciao,
Matteo

 
http://en.wikipedia.org/wiki/Singleton_pattern
Temo non sia esattamente quello che mi serve.
  bye & Thanks
	av.
P.S. Forse siamo al limite dell'OT, ve ne chiedo scusa.


Ciao,
Matteo

 libreria.
Questo mi torna. Il linking di una libreria � fatto apposta per 
includere solamente il codice che viene effettivamente utilizzato.
Avere una libreria che ha effetti collaterali per il solo fatto di 
essere linkata, sarebbe alquanto strano. Devi presentare all'utente 
della libreria una funzione "init" che procede ad inizializzare la 
variabile incriminata.
E.

 E.
Su Windows, credo di sì, tant'è che ci sono i DLL entry point da
definire e le macro DLLEXPORT & co.
Non è necessariamente vero per sistemi GNU/Linux o Unix-based. Basta
dire al linker che si sta creando un DSO; da cui il flag "-shared" al
compilatore ed eventualmente -fPIC o -fpic. I simboli sono normalmente
esportati a meno che non si usi -fvisibility=hidden o si strippi
manualmente l'oggetto risultante.
Certo, se non si dice al linker che si sta creando una libreria, non
sa di dover esportare i simboli come dinamici (cfr. man ld, opzione "--
export-dynamic" e compagne, che dovrebbero essere automaticamente
abilitate da g++ -shared).
Ad ogni modo, se sei in dubbio, usa libtool che fai prima.
Matteo

 Forse non ho capito cosa vuoi ottenere. Comunque, vedi tu.
Per quanto ne so io, un singleton viene creato/inizializzato al primo 
uso; nel mio caso, invece, il problema e' proprio che ho un oggetto 
statico che non viene mai usato.
Questo dovrebbe semplicemente registrare una classe in un elenco (e' 
lunga spiegare il come e il perche'); probabilmente in effetti si puo' 
trovare un'altra soluzione, ma vorrei comunque arrivare a capire la 
situazione attuale.
  bye & Thanks
	av.
P.S. Per tutti gli altri che mi hanno risposto; appena avro' l'occasione 
provero' anche i vostri suggerimenti.


Allora ha ragione ?manu*, definisci la funzione _init() e linka con i
flag giusti.
Credo ci sia nella pagina di manuale di dlopen.
Ciao,
Matteo

 Credo ci sia nella pagina di manuale di dlopen.
Ribadisco che non sto usando linking dinamico, ne' su FreeBSD (su cui 
non ho intenzione di farlo), ne' su Windows (per ora).
A margine, ho letto che _init() e' obsoleta (probabilmente non ancora su 
tutte le piattaforme), e che al suo posto si dovrebbe usare 
__attribute__ ((constructor)).
Comunque ho trovato due soluzioni al mio problema.
a) Su gcc utilizzare l'opzione del linker -whole-archive.
Il makefile del caso precedente, diventerebbe quindi:
ALL: good.exe bad.exe
%.o: %.cxx ; g++ -c -o $@ $^
b.lib: a.o ; ar rs $@ $^
bad.exe: d.o b.lib ; g++ -o $@ -Wl,-whole-archive $^ -Wl,-no-whole-archive
good.exe: a.o d.o ; g++ -o $@ $^
Ovviamente questo riguarda TUTTE le variabili globali e puo' avere molti 
piu' effetti di quelli cercati.
Un equivalente per VC++ non l'ho trovato.
b) Spostare la definizione della variabile globale dal .cxx al .hxx; 
ovviamente avremo un errore perche' il simbolo sara' definito in piu' 
file oggetto, ma basta renderlo "week" o "COMDAT" (risp. nelle 
terminologie di gcc e VC).
Quindi, sempre nell'esempio precedente Prova sparisce da a.cxx e a.hxx 
diventa:
#include <iostream>
#include <string>
struct I {
   I(const std::string&i) {std::cout<<i<<std::endl;}
};
#ifdef _MSC_VER
__declspec(selectany) I Prova("prova");
#else
I __attribute__((__weak__)) Prova("prova");
#endif
Questo consente di limitare gli effetti alla singola variabile.
(Ovviamente non essendoci altro in a, non ha piu' senso fare una 
libreria, ma e' solo un effetto dell'usare un esempio minimo).
Grazie a tutti quelli che mi hanno risposto.
  bye
	av.

 A margine, ho letto che _init() e' obsoleta 
Io non mi riferivo al linking dinamico. Secondo me la soluzione migliore 
� chiedere all'utente della libreria di chiamare *esplicitamente* una 
funzione init(), o MYLIBinit() o come vuoi chiamarla, che si preoccupa 
di inizializzare i dati statici.
Probabilmente dipende dal fatto che non ho piena conoscenza del problema 
che devi risolvere, ma mi sembra molto brutto affidarsi agli effetti 
collaterali dell'inizializzazione di una variabile che non viene mai 
utilizzata. Io in tutti i modi cercherei di evitarlo.
E.