RE: [ROOT] streamers for nested stl containers

From: Philippe Canal (pcanal@popgtw.fnal.gov)
Date: Fri Aug 11 2000 - 18:14:34 MEST


Hi,

As you noted the streamer automatically created by rootcint is forgetting
to 'clean' the vector before reading the streamer.

For greater flexibility a Streamer should not assume that the object it
is reading is clean and should insure clean-up. (To allow loop like
in the Y::Streamer).

This problem should be fixed shortly in the cvs repository.

Philippe.

> -----Original Message-----
> From: owner-roottalk@pcroot.cern.ch
> [mailto:owner-roottalk@pcroot.cern.ch]On Behalf Of Matevz Tadel
> Sent: Tuesday, August 08, 2000 9:10 AM
> To: roottalk@pcroot.cern.ch
> Subject: [ROOT] streamers for nested stl containers
> 
> 
> Hi,
> 
> Imagine a situation:
> 
> X.h <<fnord
> #ifndef _x_h_
> #define _x_h_
> 
> #include <TNamed.h>
> #include <vector>
> #include <iostream>
> 
> class X : public TNamed {
> public:
>   vector<int>	mV;
> 
>   X(const Text_t* n="x") : TNamed(n,0) {}
>   void Populate(Int_t M=3) { for(int i=0; i<M; i++) mV.push_back(i); }
>   void Spit() {
>     cout << GetName() <<": [";
>     for(vector<int>::iterator i=mV.begin(); i!=mV.end(); i++) cout
> <<*i<<" ";
>     cout <<"]\n";
>   }
> 
>   ClassDef(X,1)
> };
> 
> #endif
> fnord
> 
> Y.h << fnord
> #ifndef _y_h_
> #define _y_h_
> 
> #include "X.h"
> #include <TObject.h>
> #include <vector>
> 
> class Y : public TObject {
> public:
>   vector<X>	mX;
> 
>   void Populate(Int_t M=3) {
>     char a='A', n[2]; for(int i=0; i<M; i++,a++) {
>       sprintf(n,"%c",a);
>       X x(n); x.Populate(i+1);
>       mX.push_back(x);
>     }
>   }
>   void Spit() { for(vector<X>::iterator
> i=mX.begin(); i!=mX.end(); i++) i->Spit(); }
>   ClassDef(Y,1)
> };
> 
> #endif
> fnord
> 
> root session 1:
> root [0] #include <vector>              
> root [1] gSystem->Load("libElDictos.so")
> (int)0
> root [2] Y y
> root [3] y.Populate()
> root [4] y.Spit()
> A: [0 ]
> B: [0 1 ]
> C: [0 1 2 ]
> root [5] TFile f("xy.root","RECREATE")
> root [6] y.Write("Y")      
> (Int_t)134
> root [7] f.Close()
> root [8] .q
> 
> root session 2:
> root [0] #include <vector>              
> root [1] gSystem->Load("libElDictos.so")
> (int)0
> root [2] TFile f("xy.root")
> root [3] .ls
> TFile**         xy.root
>  TFile*         xy.root
>   KEY: Y        Y;1
> root [4] Y.Spit()
> A: [0 ]
> B: [0 0 1 ]
> C: [0 0 1 0 1 2 ]
> 
> Conclusion:
> Reading of stl container fails, if its elements contain further stl
> containers ...
> eg:
>    // Stream an object of class Y.
>    if (R__b.IsReading()) {
>       Version_t R__v = R__b.ReadVersion(); if (R__v) { }
>       TObject::Streamer(R__b);
>       {
>          int R__i, R__n;
>          X R__t;          //!! should be inside loop !!
>          R__b >> R__n;
>          for (R__i = 0; R__i < R__n; R__i++) {
>             R__t.Streamer(R__b);
>             mX.push_back(R__t);
>          }
>       }
>    } else { ...
> 
> perhaps i live in a dream world, but i would expect the code with
> declaration inside the loop consume the same number of constructors (due
> to optimizations for a variable going out of scope copy constructor for
> stl element is not called). In this case it has to be invoked anyway
> ... we just gain one destruction (which isn't called if my dream
> optimization really exists)
> 
> huh ... back to my histograms ...
> 
> cheers,
> matevz
> 
> -- 
> ---------------------------------------------------
>  Matevz Tadel,         E-mail: Matevz.Tadel@ijs.si 
>  Department of Experimental High Energy Physics F9 
>  Jozef Stefan Institute,  Jamova 39,  P.o.Box 3000 
>  SI-1001 Ljubljana, Slovenia                       
>  Tel.: +386-61-177-3674      Fax: +386-61-125-7074 
> ---------------------------------------------------
> 
> 



This archive was generated by hypermail 2b29 : Tue Jan 02 2001 - 11:50:31 MET