Newsgroup: it.comp.lang.c++
Titolo: Implementazione di una map<string, ANY>

Hi all
Il subject non é sta gran chiarezza, per cui vedo di spiegarmi.
Mio scopo é produrre una "property map" generica, cioé che a fronte di
chiavi testuali, sia in grado di contenere e restituire qualsiasi tipo di 
valore, mantenendo però informazioni sul tipo, e che sia semplice da usare.
Come metodi dovrebbe avere (lasciando fuori per un attimo roba allocata
dinamicamente):
template<typename T>
	void Set (const string key, const T& value)
	throw();
template<typename T>
	T& Get(const string key)
	throw (qualche_eccezione);
Al momento ho risolto convertendo gli oggetti in una string con
boost::lexical_cast e memorizzando, insieme alla string, anche il typeid
originale. In fase di Get controllo che il typeid richiesto sia uguale
all'originale. Chiaramente, é una soluzione da due soldi.
Mi piacerebbe avere altri pareri, tenendo conto che:
*) La possibilità di interagire con la property map non deve essere
intrusiva, cioé non deve richiedere alcuna modifica al tipo da memorizzare.
*) Non bisogna farsi troppe seghe mentali. Per memorizzare classi di
complessità arbitraria posso usare un serializzatore. Questa ha uno scopo
più limitato.
*) Per oggetti allocati dinamicamente, alla prossima puntata.
Vanno benissimo anche puntatori a discussioni/codice già fatti. Non ho
ribaltato il web, ma al momento non ho trovato nulla che mi soddisfi
completamente.
-- 
  Giuseppe "Cowo" Corbelli \/\ My software: 
http://cowo.yoda2000.net
    **ANTI-SPAM** -- **Substitute IHATESPAM with cowo to reply by mail**
-<! Computer programmers never die, they just raise an unhandled exception.!>-

 usare. 
Grosso modo la mia idea sarebbe questa. Dunque, la map<> dovrà contenere 
puntatori e in qualche modo dovremo usare l'RTTI. Poiché non possiamo 
modificare i tipi esistenti, useremo dei wrapper:
  class anything  { public: ~anything() { } }; 
  template< class T >
  struct something : public anything
  {     T value:
        something( const T& v ) : value(v) { }
  };
Basiamo la nostra implementazione su un
    std::map< std::string, anything* > my_map;
'Set' e Get potranno più o meno essere implementati così:
 template<typename T>
 void Set (const string key, const T& value)
 {
        // eliminiamo eventuale chiave omonima esistente ... 
        // [...]    
        something<T>*   new_value = new something<T>(value);
        my_map[ key ] = new_value;
        // ovviamente si può ottimizzare, sfruttando il risultato della
        // ricerca per effettuare l'inserimento
 }
 template<typename T>
 T& Get(const string key)
  {
        anything* v = my_map[key];
        if( something<T>* sv = dynamic_cast< something<T>* >(v) )
          return sv->value;
        else 
          throw some_exception();
  }
Max

 dinamicamente):
Direi che boost::any fa per te:
http://www.boost.org/doc/html/boost/any.html
Ciao.
-- 
BSD is for UNIX lovers -- linux is for Windows haters.

 
http://www.boost.org/doc/html/boost/any.html
Thanks. I know it, quando posso uso boost pure io. Il problema derivava
infatti dal fatto che in boost la "property map" come intendo io c'é, ma é 
complessa da usare, per cui volevo provare un'implementazione completamente
alternativa, più che altro per fini di conoscenza che non di vera utilità.
-- 
  Giuseppe "Cowo" Corbelli \/\ My software: 
http://cowo.yoda2000.net
    **ANTI-SPAM** -- **Substitute IHATESPAM with cowo to reply by mail**
  -<! Any sufficiently advanced bug is indistinguishable from a feature. !>-
                 Rich Kulawiec

   }
Pensavo di memorizzare il typeid in fase di Set e poi assicurarmi
dell'equivalenza di quello richiesto in fase di Get.
Grazie per l'idea, spero di farne buon uso!
-- 
  Giuseppe "Cowo" Corbelli \/\ My software: 
http://cowo.yoda2000.net
    **ANTI-SPAM** -- **Substitute IHATESPAM with cowo to reply by mail**


 Grazie per l'idea, spero di farne buon uso!
Nota che boost::any, suggerito da H.P.L., utilizza sostanzialmente la 
stessa tecnica, però incapsula la gestione del lifetime e della copia 
(clone) degli oggetti wrapper in una classe che soddisfa i requisiti per 
essere usata come valore in un container e usa una funzione template 
esterna (any_cast<>) per il cast del valore.
Con boost::any, ti basterà dichiarare un std::map<std::string,boost::any>. 
Max

 alternativa, più che altro per fini di conoscenza che non di vera utilità.
No, scusami, non sono stato abbastanza chiaro.
boost::any non è una property map ma è proprio l'ANY che intendevi tu
(il Variant del Visual Basic se sai cos'è), cioé un contenitore che può
contenere un tipo di dato qualunque.


 No, scusami, non sono stato abbastanza chiaro.
...
Sei stato chiarissimo, già nel primo reply.
boost::any mi va benissimo, fa esattamente quello che voglio, e ora ho pure
scoperto grossomodo come funziona, cosa che non guasta mai.
-- 
  Giuseppe "Cowo" Corbelli \/\ My software: 
http://cowo.yoda2000.net
    **ANTI-SPAM** -- **Substitute IHATESPAM with cowo to reply by mail**
  -<! I Never Wanted To Be What They Told Me To Be
  		Fulfill My Fate Then I'll Be Free >!- Blind Guardian - Mordred's Song

 Con boost::any, ti basterà dichiarare un std::map<std::string,boost::any>. 
Certo. Ho esitato a fare direttamente così perché:
*) in boost la "property map generica" già c'é, ma ha usabilità molto
scarsa. Volevo proporre un'implementazione alternativa.
*) Volevo capire come funziona la faccenda.
-- 
  Giuseppe "Cowo" Corbelli \/\ My software: 
http://cowo.yoda2000.net
    **ANTI-SPAM** -- **Substitute IHATESPAM with cowo to reply by mail**
